From 600db9fdf9354c75c42724428f784a2a85625cbd Mon Sep 17 00:00:00 2001 From: acolytec3 <17355484+acolytec3@users.noreply.github.com> Date: Mon, 27 Mar 2023 13:41:41 -0400 Subject: [PATCH 01/53] `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 --- package-lock.json | 48 +-- packages/block/src/block.ts | 59 ++-- packages/block/src/from-rpc.ts | 4 +- packages/block/src/header.ts | 201 +++++------ packages/block/src/helpers.ts | 4 +- packages/block/src/types.ts | 44 +-- packages/block/test/block.spec.ts | 58 ++-- packages/block/test/clique.spec.ts | 39 +-- packages/block/test/difficulty.spec.ts | 3 +- packages/block/test/eip1559block.spec.ts | 13 +- packages/block/test/eip4844block.spec.ts | 12 +- packages/block/test/eip4895block.spec.ts | 34 +- packages/block/test/from-rpc.spec.ts | 24 +- packages/block/test/header.spec.ts | 104 +++--- packages/block/test/mergeBlock.spec.ts | 35 +- packages/block/test/util.ts | 6 +- packages/blockchain/src/blockchain.ts | 107 +++--- packages/blockchain/src/consensus/clique.ts | 89 +++-- packages/blockchain/src/db/cache.ts | 21 +- packages/blockchain/src/db/constants.ts | 33 +- packages/blockchain/src/db/helpers.ts | 17 +- packages/blockchain/src/db/manager.ts | 56 +-- packages/blockchain/src/db/operation.ts | 18 +- .../blockchain/src/genesisStates/index.ts | 17 +- packages/blockchain/src/types.ts | 8 +- .../blockchain/test/blockValidation.spec.ts | 13 +- packages/blockchain/test/clique.spec.ts | 117 +++---- .../blockchain/test/customConsensus.spec.ts | 3 +- packages/blockchain/test/index.spec.ts | 105 +++--- packages/blockchain/test/iterator.spec.ts | 22 +- packages/blockchain/test/pos.spec.ts | 3 +- packages/blockchain/test/reorg.spec.ts | 15 +- packages/blockchain/test/util.ts | 64 ++-- packages/blockchain/test/utils.spec.ts | 5 +- packages/client/bin/cli.ts | 39 ++- packages/client/bin/startRpc.ts | 14 +- packages/client/browser/index.ts | 4 +- packages/client/browser/util/index.ts | 13 +- .../devnets/4844-interop/tools/txGenerator.ts | 8 +- packages/client/lib/blockchain/chain.ts | 20 +- packages/client/lib/client.ts | 6 +- packages/client/lib/config.ts | 19 +- packages/client/lib/execution/execution.ts | 8 +- packages/client/lib/execution/level.ts | 12 +- packages/client/lib/execution/receipt.ts | 98 +++--- packages/client/lib/execution/vmexecution.ts | 28 +- packages/client/lib/miner/miner.ts | 18 +- packages/client/lib/miner/pendingBlock.ts | 74 ++-- packages/client/lib/net/peer/rlpxpeer.ts | 4 +- .../client/lib/net/protocol/ethprotocol.ts | 126 +++---- .../client/lib/net/protocol/lesprotocol.ts | 86 ++--- .../client/lib/net/protocol/libp2psender.ts | 23 +- packages/client/lib/net/protocol/sender.ts | 2 +- .../client/lib/net/protocol/snapprotocol.ts | 94 +++--- packages/client/lib/net/server/rlpxserver.ts | 15 +- packages/client/lib/net/server/server.ts | 2 +- packages/client/lib/rpc/helpers.ts | 6 +- packages/client/lib/rpc/modules/admin.ts | 6 +- packages/client/lib/rpc/modules/debug.ts | 11 +- packages/client/lib/rpc/modules/engine.ts | 91 ++--- packages/client/lib/rpc/modules/eth.ts | 81 ++--- packages/client/lib/rpc/modules/web3.ts | 4 +- .../client/lib/service/ethereumservice.ts | 6 +- .../client/lib/service/fullethereumservice.ts | 7 +- packages/client/lib/service/txpool.ts | 44 +-- packages/client/lib/sync/beaconsync.ts | 6 +- .../client/lib/sync/fetcher/accountfetcher.ts | 68 ++-- .../client/lib/sync/fetcher/blockfetcher.ts | 12 +- .../client/lib/sync/fetcher/storagefetcher.ts | 85 ++--- packages/client/lib/sync/fullsync.ts | 19 +- packages/client/lib/sync/skeleton.ts | 112 +++--- packages/client/lib/sync/snapsync.ts | 5 +- packages/client/lib/types.ts | 2 +- packages/client/lib/util/debug.ts | 12 +- packages/client/lib/util/index.ts | 13 +- packages/client/lib/util/metaDBManager.ts | 16 +- packages/client/lib/util/parse.ts | 12 +- packages/client/lib/util/rpc.ts | 4 +- packages/client/test/blockchain/chain.spec.ts | 6 +- .../integration/fullethereumservice.spec.ts | 19 +- .../client/test/integration/merge.spec.ts | 8 +- .../client/test/integration/miner.spec.ts | 8 +- .../client/test/integration/mocks/mockpeer.ts | 2 +- packages/client/test/miner/miner.spec.ts | 28 +- .../client/test/miner/pendingBlock.spec.ts | 38 +-- .../test/net/protocol/ethprotocol.spec.ts | 57 ++-- .../test/net/protocol/lesprotocol.spec.ts | 29 +- .../test/net/protocol/libp2psender.spec.ts | 11 +- .../test/net/protocol/snapprotocol.spec.ts | 142 ++++---- .../test/net/server/libp2pserver.spec.ts | 7 +- .../client/test/net/server/rlpxserver.spec.ts | 20 +- .../test/rpc/debug/traceTransaction.spec.ts | 10 +- .../rpc/engine/forkchoiceUpdatedV1.spec.ts | 10 +- .../test/rpc/engine/getBlobsBundleV1.spec.ts | 7 +- .../engine/getPayloadBodiesByHashV1.spec.ts | 29 +- .../engine/getPayloadBodiesByRangeV1.spec.ts | 14 +- .../test/rpc/engine/newPayloadV1.spec.ts | 13 +- .../test/rpc/engine/newPayloadv2.spec.ts | 13 +- .../test/rpc/engine/newPayloadv3.spec.ts | 13 +- .../test/rpc/engine/withdrawals.spec.ts | 6 +- packages/client/test/rpc/eth/call.spec.ts | 14 +- .../test/rpc/eth/getBlockByNumber.spec.ts | 11 +- packages/client/test/rpc/eth/getLogs.spec.ts | 14 +- .../client/test/rpc/eth/getStorageAt.spec.ts | 15 +- .../test/rpc/eth/getTransactionByHash.spec.ts | 14 +- .../rpc/eth/getTransactionReceipt.spec.ts | 10 +- .../eth/getUncleCountByBlockNumber.spec.ts | 2 +- .../test/rpc/eth/sendRawTransaction.spec.ts | 26 +- packages/client/test/rpc/helpers.ts | 10 +- packages/client/test/rpc/mockBlockchain.ts | 6 +- packages/client/test/rpc/rpc.spec.ts | 3 +- .../client/test/rpc/txpool/content.spec.ts | 2 +- packages/client/test/rpc/validation.spec.ts | 35 +- packages/client/test/rpc/websocket.spec.ts | 3 +- .../test/service/fullethereumservice.spec.ts | 27 +- packages/client/test/sim/eof.spec.ts | 6 +- packages/client/test/sim/mainnet.spec.ts | 6 +- packages/client/test/sim/sharding.spec.ts | 15 +- packages/client/test/sim/simutils.ts | 47 +-- packages/client/test/sim/snapsync.spec.ts | 5 +- packages/client/test/sim/txGenerator.ts | 27 +- packages/client/test/sync/beaconsync.spec.ts | 4 +- .../test/sync/fetcher/accountfetcher.spec.ts | 62 ++-- .../test/sync/fetcher/storagefetcher.spec.ts | 116 +++---- packages/client/test/sync/fullsync.spec.ts | 2 +- packages/client/test/sync/lightsync.spec.ts | 6 +- packages/client/test/sync/skeleton.spec.ts | 9 +- packages/client/test/sync/sync.spec.ts | 2 +- packages/client/test/sync/txpool.spec.ts | 56 +-- packages/client/test/util/rpc.spec.ts | 10 +- packages/common/src/common.ts | 25 +- packages/common/src/types.ts | 2 +- packages/common/test/hardforks.spec.ts | 18 +- packages/common/test/timestamp.spec.ts | 11 +- packages/common/test/utils.spec.ts | 6 +- .../devp2p/examples/peer-communication-les.ts | 31 +- .../devp2p/examples/peer-communication.ts | 46 ++- packages/devp2p/examples/simple.ts | 9 +- packages/devp2p/package.json | 3 - packages/devp2p/scripts/singlePeerRun.ts | 2 +- .../devp2p/src/@types/snappyjs/index.d.ts | 4 +- packages/devp2p/src/dns/enr.ts | 28 +- packages/devp2p/src/dpt/ban-list.ts | 4 +- packages/devp2p/src/dpt/dpt.ts | 24 +- packages/devp2p/src/dpt/kbucket.ts | 19 +- packages/devp2p/src/dpt/message.ts | 106 +++--- packages/devp2p/src/dpt/server.ts | 27 +- packages/devp2p/src/protocol/eth.ts | 87 +++-- packages/devp2p/src/protocol/les.ts | 83 ++--- packages/devp2p/src/protocol/protocol.ts | 2 +- packages/devp2p/src/protocol/snap.ts | 3 +- packages/devp2p/src/rlpx/ecies.ts | 258 +++++++------- packages/devp2p/src/rlpx/mac.ts | 12 +- packages/devp2p/src/rlpx/peer.ts | 125 +++---- packages/devp2p/src/rlpx/rlpx.ts | 48 +-- packages/devp2p/src/util.ts | 165 ++++++--- packages/devp2p/test/dpt-message.spec.ts | 43 +-- packages/devp2p/test/enr.spec.ts | 6 +- .../test/integration/dpt-simulator.spec.ts | 13 +- .../test/integration/eth-simulator.spec.ts | 15 +- .../test/integration/les-simulator.spec.ts | 13 +- .../test/integration/rlpx-simulator.spec.ts | 3 +- packages/devp2p/test/integration/util.ts | 2 +- packages/devp2p/test/rlpx-ecies.spec.ts | 53 +-- packages/devp2p/test/rlpx-mac.spec.ts | 16 +- packages/ethash/examples/example.ts | 8 +- packages/ethash/examples/rawExample.ts | 21 +- packages/ethash/package.json | 1 + packages/ethash/src/index.ts | 123 ++++--- packages/ethash/src/util.ts | 21 +- packages/ethash/test/block.spec.ts | 15 +- packages/ethash/test/ethash.spec.ts | 16 +- packages/ethash/test/miner.spec.ts | 13 +- packages/evm/examples/decode-opcodes.ts | 17 +- packages/evm/examples/runCode.ts | 5 +- packages/evm/package.json | 3 +- packages/evm/src/eof.ts | 10 +- packages/evm/src/evm.ts | 54 +-- packages/evm/src/interpreter.ts | 120 ++++--- packages/evm/src/memory.ts | 27 +- packages/evm/src/message.ts | 26 +- packages/evm/src/opcodes/EIP1283.ts | 20 +- packages/evm/src/opcodes/EIP2200.ts | 22 +- packages/evm/src/opcodes/EIP2929.ts | 14 +- packages/evm/src/opcodes/functions.ts | 117 +++---- packages/evm/src/opcodes/gas.ts | 42 +-- packages/evm/src/opcodes/util.ts | 34 +- packages/evm/src/precompiles/01-ecrecover.ts | 40 +-- packages/evm/src/precompiles/02-sha256.ts | 14 +- packages/evm/src/precompiles/03-ripemd160.ts | 14 +- packages/evm/src/precompiles/04-identity.ts | 8 +- packages/evm/src/precompiles/05-modexp.ts | 47 +-- packages/evm/src/precompiles/06-ecadd.ts | 15 +- packages/evm/src/precompiles/07-ecmul.ts | 16 +- packages/evm/src/precompiles/08-ecpairing.ts | 13 +- packages/evm/src/precompiles/09-blake2f.ts | 39 +-- .../evm/src/precompiles/0a-bls12-g1add.ts | 23 +- .../evm/src/precompiles/0b-bls12-g1mul.ts | 23 +- .../src/precompiles/0c-bls12-g1multiexp.ts | 25 +- .../evm/src/precompiles/0d-bls12-g2add.ts | 21 +- .../evm/src/precompiles/0e-bls12-g2mul.ts | 23 +- .../src/precompiles/0f-bls12-g2multiexp.ts | 25 +- .../evm/src/precompiles/10-bls12-pairing.ts | 35 +- .../src/precompiles/11-bls12-map-fp-to-g1.ts | 21 +- .../src/precompiles/12-bls12-map-fp2-to-g2.ts | 23 +- .../precompiles/14-kzg-point-evaluation.ts | 55 +-- packages/evm/src/precompiles/index.ts | 8 +- packages/evm/src/precompiles/types.ts | 2 +- .../evm/src/precompiles/util/bls12_381.ts | 73 ++-- packages/evm/src/transientStorage.ts | 22 +- packages/evm/src/types.ts | 52 +-- packages/evm/test/asyncEvents.spec.ts | 5 +- packages/evm/test/customOpcodes.spec.ts | 13 +- packages/evm/test/customPrecompiles.spec.ts | 48 +-- packages/evm/test/eips/eip-3860.spec.ts | 60 ++-- packages/evm/test/eof.spec.ts | 5 +- packages/evm/test/memory.spec.ts | 12 +- .../evm/test/precompiles/06-ecadd.spec.ts | 2 +- .../evm/test/precompiles/07-ecmul.spec.ts | 2 +- .../evm/test/precompiles/08-ecpairing.spec.ts | 7 +- .../precompiles/14-pointevaluation.spec.ts | 47 ++- .../evm/test/precompiles/eip-2537-BLS.spec.ts | 15 +- .../evm/test/precompiles/hardfork.spec.ts | 3 +- packages/evm/test/runCall.spec.ts | 144 ++++---- packages/evm/test/runCode.spec.ts | 7 +- packages/evm/test/stack.spec.ts | 13 +- packages/evm/test/transientStorage.spec.ts | 60 ++-- packages/statemanager/src/baseStateManager.ts | 6 +- packages/statemanager/src/cache.ts | 14 +- .../statemanager/src/ethersStateManager.ts | 81 ++--- packages/statemanager/src/interface.ts | 16 +- packages/statemanager/src/stateManager.ts | 129 +++---- packages/statemanager/test/cache.spec.ts | 24 +- .../test/ethersStateManager.spec.ts | 32 +- .../test/proofStateManager.spec.ts | 66 ++-- .../statemanager/test/stateManager.spec.ts | 151 ++++----- packages/trie/benchmarks/engines/level.ts | 14 +- packages/trie/benchmarks/keys.ts | 4 +- packages/trie/benchmarks/suite.ts | 6 +- packages/trie/examples/level.js | 2 +- packages/trie/recipes/level-legacy.ts | 8 +- packages/trie/recipes/level.ts | 20 +- packages/trie/recipes/lmdb.ts | 6 +- packages/trie/src/db/checkpoint.ts | 24 +- packages/trie/src/db/map.ts | 18 +- packages/trie/src/proof/range.ts | 42 +-- packages/trie/src/trie/node/branch.ts | 11 +- packages/trie/src/trie/node/extension.ts | 2 +- packages/trie/src/trie/node/leaf.ts | 2 +- packages/trie/src/trie/node/node.ts | 17 +- packages/trie/src/trie/node/util.ts | 13 +- packages/trie/src/trie/trie.ts | 120 +++---- packages/trie/src/types.ts | 36 +- packages/trie/src/util/nibbles.ts | 16 +- packages/trie/src/util/readStream.ts | 4 +- packages/trie/src/util/walkController.ts | 14 +- packages/trie/test/db/checkpoint.spec.ts | 22 +- packages/trie/test/db/db.spec.ts | 13 +- packages/trie/test/encoding.spec.ts | 8 +- packages/trie/test/index.spec.ts | 196 +++++------ packages/trie/test/official.spec.ts | 27 +- packages/trie/test/proof.spec.ts | 117 +++---- packages/trie/test/proof/range.spec.ts | 84 +++-- packages/trie/test/stream.spec.ts | 91 ++--- packages/trie/test/trie/checkpoint.spec.ts | 91 ++--- packages/trie/test/trie/prune.spec.ts | 108 +++--- packages/trie/test/trie/secure.spec.ts | 120 +++---- packages/trie/test/trie/trie.spec.ts | 26 +- packages/tx/examples/custom-chain-tx.ts | 6 +- packages/tx/examples/ropsten-tx.ts | 4 +- packages/tx/examples/transactions.ts | 12 +- packages/tx/src/baseTransaction.ts | 64 ++-- packages/tx/src/eip1559Transaction.ts | 103 +++--- packages/tx/src/eip2930Transaction.ts | 106 +++--- packages/tx/src/eip4844Transaction.ts | 129 ++++--- packages/tx/src/fromRpc.ts | 4 +- packages/tx/src/legacyTransaction.ts | 94 +++--- packages/tx/src/transactionFactory.ts | 18 +- packages/tx/src/types.ts | 76 ++--- packages/tx/src/util.ts | 38 +-- packages/tx/src/utils/blobHelpers.ts | 40 +-- packages/tx/test/base.spec.ts | 49 +-- packages/tx/test/eip1559.spec.ts | 44 +-- packages/tx/test/eip3860.spec.ts | 12 +- packages/tx/test/eip4844.spec.ts | 48 +-- packages/tx/test/fromRpc.spec.ts | 5 +- packages/tx/test/inputValue.spec.ts | 22 +- packages/tx/test/legacy.spec.ts | 134 ++++---- packages/tx/test/testLoader.ts | 5 +- packages/tx/test/transactionFactory.spec.ts | 9 +- packages/tx/test/transactionRunner.ts | 6 +- packages/tx/test/typedTxsAndEIP2930.spec.ts | 126 +++---- packages/util/src/account.ts | 152 +++++---- packages/util/src/address.ts | 60 ++-- packages/util/src/bytes.ts | 319 ++++++++++-------- packages/util/src/constants.ts | 10 +- packages/util/src/helpers.ts | 6 +- packages/util/src/index.ts | 2 +- packages/util/src/internal.ts | 8 +- packages/util/src/signature.ts | 101 +++--- packages/util/src/types.ts | 49 ++- packages/util/src/withdrawal.ts | 45 ++- packages/util/test/account.spec.ts | 270 +++++++-------- packages/util/test/address.spec.ts | 31 +- packages/util/test/bytes.spec.ts | 299 +++++++--------- packages/util/test/constants.spec.ts | 7 +- packages/util/test/encoding.spec.ts | 19 +- packages/util/test/internal.spec.ts | 5 +- packages/util/test/signature.spec.ts | 191 +++++------ packages/util/test/ssz.spec.ts | 31 +- packages/util/test/types.spec.ts | 52 +-- packages/util/test/withdrawal.spec.ts | 27 +- packages/vm/benchmarks/mockchain.ts | 2 +- packages/vm/benchmarks/util.ts | 20 +- packages/vm/examples/helpers/account-utils.ts | 2 +- packages/vm/examples/run-blockchain.ts | 21 +- packages/vm/examples/run-solidity-contract.ts | 25 +- packages/vm/src/bloom/index.ts | 20 +- packages/vm/src/buildBlock.ts | 14 +- packages/vm/src/eei/eei.ts | 12 +- packages/vm/src/eei/vmState.ts | 71 ++-- packages/vm/src/runBlock.ts | 71 ++-- packages/vm/src/runTx.ts | 36 +- packages/vm/src/types.ts | 16 +- packages/vm/src/vm.ts | 13 +- packages/vm/test/api/EIPs/eip-1153.spec.ts | 26 +- .../EIPs/eip-1283-net-gas-metering.spec.ts | 13 +- .../test/api/EIPs/eip-1559-FeeMarket.spec.ts | 15 +- packages/vm/test/api/EIPs/eip-2315.spec.ts | 3 +- .../api/EIPs/eip-2565-modexp-gas-cost.spec.ts | 11 +- packages/vm/test/api/EIPs/eip-2929.spec.ts | 21 +- .../api/EIPs/eip-2930-accesslists.spec.ts | 18 +- .../test/api/EIPs/eip-3074-authcall.spec.ts | 301 +++++++++-------- .../vm/test/api/EIPs/eip-3198-BaseFee.spec.ts | 5 +- packages/vm/test/api/EIPs/eip-3529.spec.ts | 21 +- .../EIPs/eip-3540-evm-object-format.spec.ts | 30 +- packages/vm/test/api/EIPs/eip-3541.spec.ts | 3 +- packages/vm/test/api/EIPs/eip-3607.spec.ts | 4 +- .../api/EIPs/eip-3651-warm-coinbase.spec.ts | 9 +- .../EIPs/eip-3670-eof-code-validation.spec.ts | 41 ++- packages/vm/test/api/EIPs/eip-3855.spec.ts | 9 +- packages/vm/test/api/EIPs/eip-3860.spec.ts | 7 +- ...t-difficulty-opcode-with-prevrando.spec.ts | 7 +- .../api/EIPs/eip-4895-withdrawals.spec.ts | 57 ++-- packages/vm/test/api/bloom.spec.ts | 44 +-- packages/vm/test/api/buildBlock.spec.ts | 54 +-- packages/vm/test/api/customChain.spec.ts | 10 +- packages/vm/test/api/eei.spec.ts | 3 +- packages/vm/test/api/events.spec.ts | 14 +- packages/vm/test/api/index.spec.ts | 12 +- .../vm/test/api/istanbul/eip-1108.spec.ts | 10 +- .../vm/test/api/istanbul/eip-1344.spec.ts | 9 +- packages/vm/test/api/istanbul/eip-152.spec.ts | 7 +- .../vm/test/api/istanbul/eip-1884.spec.ts | 11 +- .../vm/test/api/istanbul/eip-2200.spec.ts | 13 +- packages/vm/test/api/runBlock.spec.ts | 83 ++--- packages/vm/test/api/runTx.spec.ts | 59 ++-- .../vm/test/api/state/accountExists.spec.ts | 41 +-- packages/vm/test/api/utils.ts | 8 +- packages/vm/test/api/vmState.spec.ts | 57 ++-- .../vm/test/retesteth/transition-child.ts | 34 +- .../tester/runners/BlockchainTestsRunner.ts | 21 +- .../tester/runners/GeneralStateTestsRunner.ts | 10 +- packages/vm/test/tester/testLoader.ts | 4 +- packages/vm/test/util.ts | 56 ++- 365 files changed, 6609 insertions(+), 6426 deletions(-) diff --git a/package-lock.json b/package-lock.json index 2db227f050..c8ce7feaa1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4471,14 +4471,6 @@ "file-uri-to-path": "1.0.0" } }, - "node_modules/bl": { - "version": "1.2.3", - "license": "MIT", - "dependencies": { - "readable-stream": "^2.3.5", - "safe-buffer": "^5.1.1" - } - }, "node_modules/blakejs": { "version": "1.2.1", "license": "MIT" @@ -5465,6 +5457,7 @@ }, "node_modules/core-util-is": { "version": "1.0.3", + "dev": true, "license": "MIT" }, "node_modules/cors": { @@ -8578,10 +8571,6 @@ "node": ">= 0.10" } }, - "node_modules/ip": { - "version": "1.1.8", - "license": "MIT" - }, "node_modules/ip-address": { "version": "6.4.0", "license": "MIT", @@ -9080,6 +9069,7 @@ }, "node_modules/isarray": { "version": "1.0.0", + "dev": true, "license": "MIT" }, "node_modules/isbinaryfile": { @@ -13995,6 +13985,7 @@ }, "node_modules/process-nextick-args": { "version": "2.0.1", + "dev": true, "license": "MIT" }, "node_modules/process-on-spawn": { @@ -14260,6 +14251,7 @@ }, "node_modules/readable-stream": { "version": "2.3.7", + "dev": true, "license": "MIT", "dependencies": { "core-util-is": "~1.0.0", @@ -14273,10 +14265,12 @@ }, "node_modules/readable-stream/node_modules/safe-buffer": { "version": "5.1.2", + "dev": true, "license": "MIT" }, "node_modules/readable-stream/node_modules/string_decoder": { "version": "1.1.1", + "dev": true, "license": "MIT", "dependencies": { "safe-buffer": "~5.1.0" @@ -18010,13 +18004,10 @@ "@ethereumjs/rlp": "^4.0.1", "@ethereumjs/util": "^8.0.5", "@scure/base": "1.1.1", - "@types/bl": "^2.1.0", "@types/k-bucket": "^5.0.0", "@types/lru-cache": "^5.1.0", - "bl": "^1.1.2", "debug": "^4.3.3", "ethereum-cryptography": "^1.1.2", - "ip": "^1.1.3", "k-bucket": "^5.0.0", "lru-cache": "^5.1.1", "ms": "^0.7.1", @@ -19685,18 +19676,15 @@ "@ethereumjs/tx": "^4.1.1", "@ethereumjs/util": "^8.0.5", "@scure/base": "1.1.1", - "@types/bl": "^2.1.0", "@types/chalk": "^2.2.0", "@types/debug": "^4.1.4", "@types/ip": "^1.1.0", "@types/k-bucket": "^5.0.0", "@types/lru-cache": "^5.1.0", "@types/ms": "^0.7.30", - "bl": "^1.1.2", "chalk": "^2.4.2", "debug": "^4.3.3", "ethereum-cryptography": "^1.1.2", - "ip": "^1.1.3", "k-bucket": "^5.0.0", "lru-cache": "^5.1.1", "ms": "^0.7.1", @@ -21574,13 +21562,6 @@ "file-uri-to-path": "1.0.0" } }, - "bl": { - "version": "1.2.3", - "requires": { - "readable-stream": "^2.3.5", - "safe-buffer": "^5.1.1" - } - }, "blakejs": { "version": "1.2.1" }, @@ -22284,7 +22265,8 @@ "dev": true }, "core-util-is": { - "version": "1.0.3" + "version": "1.0.3", + "dev": true }, "cors": { "version": "2.8.5", @@ -24406,9 +24388,6 @@ "version": "2.2.0", "dev": true }, - "ip": { - "version": "1.1.8" - }, "ip-address": { "version": "6.4.0", "requires": { @@ -24683,7 +24662,8 @@ } }, "isarray": { - "version": "1.0.0" + "version": "1.0.0", + "dev": true }, "isbinaryfile": { "version": "4.0.10", @@ -28120,7 +28100,8 @@ "dev": true }, "process-nextick-args": { - "version": "2.0.1" + "version": "2.0.1", + "dev": true }, "process-on-spawn": { "version": "1.0.0", @@ -28309,6 +28290,7 @@ }, "readable-stream": { "version": "2.3.7", + "dev": true, "requires": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -28320,10 +28302,12 @@ }, "dependencies": { "safe-buffer": { - "version": "5.1.2" + "version": "5.1.2", + "dev": true }, "string_decoder": { "version": "1.1.1", + "dev": true, "requires": { "safe-buffer": "~5.1.0" } diff --git a/packages/block/src/block.ts b/packages/block/src/block.ts index 67c22c04b1..c9dac4bea6 100644 --- a/packages/block/src/block.ts +++ b/packages/block/src/block.ts @@ -5,10 +5,9 @@ import { BlobEIP4844Transaction, Capability, TransactionFactory } from '@ethereu import { KECCAK256_RLP, Withdrawal, - arrToBufArr, bigIntToHex, - bufArrToArr, - bufferToHex, + bytesToHex, + equalsBytes, intToHex, isHexPrefixed, ssz, @@ -20,7 +19,7 @@ import { blockFromRpc } from './from-rpc' import { BlockHeader } from './header' import { getDataGasPrice } from './helpers' -import type { BlockBuffer, BlockData, BlockOptions, JsonBlock, JsonRpcBlock } from './types' +import type { BlockBytes, BlockData, BlockOptions, JsonBlock, JsonRpcBlock } from './types' import type { Common } from '@ethereumjs/common' import type { FeeMarketEIP1559Transaction, @@ -28,7 +27,7 @@ import type { TxOptions, TypedTransaction, } from '@ethereumjs/tx' -import type { WithdrawalBuffer } from '@ethereumjs/util' +import type { WithdrawalBytes } from '@ethereumjs/util' /** * An object that represents the block. @@ -49,7 +48,7 @@ export class Block { public static async genWithdrawalsTrieRoot(wts: Withdrawal[], emptyTrie?: Trie) { const trie = emptyTrie ?? new Trie() for (const [i, wt] of wts.entries()) { - await trie.put(Buffer.from(RLP.encode(i)), arrToBufArr(RLP.encode(wt.raw()))) + await trie.put(RLP.encode(i), RLP.encode(wt.raw())) } return trie.root() } @@ -70,7 +69,7 @@ export class Block { public static async genTransactionsTrieRoot(txs: TypedTransaction[], emptyTrie?: Trie) { const trie = emptyTrie ?? new Trie() for (const [i, tx] of txs.entries()) { - await trie.put(Buffer.from(RLP.encode(i)), tx.serialize()) + await trie.put(RLP.encode(i), tx.serialize()) } return trie.root() } @@ -133,8 +132,8 @@ export class Block { * @param serialized * @param opts */ - public static fromRLPSerializedBlock(serialized: Buffer, opts?: BlockOptions) { - const values = arrToBufArr(RLP.decode(Uint8Array.from(serialized))) as BlockBuffer + public static fromRLPSerializedBlock(serialized: Uint8Array, opts?: BlockOptions) { + const values = RLP.decode(Uint8Array.from(serialized)) as BlockBytes if (!Array.isArray(values)) { throw new Error('Invalid serialized block input. Must be array') @@ -144,12 +143,12 @@ export class Block { } /** - * Static constructor to create a block from an array of Buffer values + * Static constructor to create a block from an array of Bytes values * * @param values * @param opts */ - public static fromValuesArray(values: BlockBuffer, opts?: BlockOptions) { + public static fromValuesArray(values: BlockBytes, opts?: BlockOptions) { if (values.length > 4) { throw new Error('invalid block. More values than expected were received') } @@ -163,7 +162,7 @@ export class Block { ) } - const [headerData, txsData, uhsData, withdrawalsBuffer] = values + const [headerData, txsData, uhsData, withdrawalBytes] = values const header = BlockHeader.fromValuesArray(headerData, opts) @@ -199,7 +198,7 @@ export class Block { uncleHeaders.push(BlockHeader.fromValuesArray(uncleHeaderData, uncleOpts)) } - const withdrawals = (withdrawalsBuffer as WithdrawalBuffer[]) + const withdrawals = (withdrawalBytes as WithdrawalBytes[]) ?.map(([index, validatorIndex, address, amount]) => ({ index, validatorIndex, @@ -312,27 +311,27 @@ export class Block { } /** - * Returns a Buffer Array of the raw Buffers of this block, in order. + * Returns a Array of the raw Bytes Arays of this block, in order. */ - raw(): BlockBuffer { - const bufferArray = [ + raw(): BlockBytes { + const bytesArray = [ this.header.raw(), this.transactions.map((tx) => tx.supports(Capability.EIP2718TypedTransaction) ? tx.serialize() : tx.raw() - ) as Buffer[], + ) as Uint8Array[], this.uncleHeaders.map((uh) => uh.raw()), ] const withdrawalsRaw = this.withdrawals?.map((wt) => wt.raw()) if (withdrawalsRaw) { - bufferArray.push(withdrawalsRaw) + bytesArray.push(withdrawalsRaw) } - return bufferArray + return bytesArray } /** * Returns the hash of the block. */ - hash(): Buffer { + hash(): Uint8Array { return this.header.hash() } @@ -346,8 +345,8 @@ export class Block { /** * Returns the rlp encoding of the block. */ - serialize(): Buffer { - return Buffer.from(RLP.encode(bufArrToArr(this.raw()))) + serialize(): Uint8Array { + return RLP.encode(this.raw()) } /** @@ -365,14 +364,14 @@ export class Block { async validateTransactionsTrie(): Promise { let result if (this.transactions.length === 0) { - result = this.header.transactionsTrie.equals(KECCAK256_RLP) + result = equalsBytes(this.header.transactionsTrie, KECCAK256_RLP) return result } - if (this.txTrie.root().equals(KECCAK256_RLP)) { + if (equalsBytes(this.txTrie.root(), KECCAK256_RLP)) { await this.genTxTrie() } - result = this.txTrie.root().equals(this.header.transactionsTrie) + result = equalsBytes(this.txTrie.root(), this.header.transactionsTrie) return result } @@ -487,8 +486,8 @@ export class Block { */ validateUnclesHash(): boolean { const uncles = this.uncleHeaders.map((uh) => uh.raw()) - const raw = RLP.encode(bufArrToArr(uncles)) - return Buffer.from(keccak256(raw)).equals(this.header.uncleHash) + const raw = RLP.encode(uncles) + return equalsBytes(keccak256(raw), this.header.uncleHash) } /** @@ -499,7 +498,7 @@ export class Block { throw new Error('EIP 4895 is not activated') } const withdrawalsRoot = await Block.genWithdrawalsTrieRoot(this.withdrawals!) - return withdrawalsRoot.equals(this.header.withdrawalsRoot!) + return equalsBytes(withdrawalsRoot, this.header.withdrawalsRoot!) } /** @@ -523,7 +522,7 @@ export class Block { } // Header does not count an uncle twice. - const uncleHashes = this.uncleHeaders.map((header) => header.hash().toString('hex')) + const uncleHashes = this.uncleHeaders.map((header) => bytesToHex(header.hash())) if (!(new Set(uncleHashes).size === uncleHashes.length)) { const msg = this._errorMsg('duplicate uncles') throw new Error(msg) @@ -572,7 +571,7 @@ export class Block { public errorStr() { let hash = '' try { - hash = bufferToHex(this.hash()) + hash = bytesToHex(this.hash()) } catch (e: any) { hash = 'error' } diff --git a/packages/block/src/from-rpc.ts b/packages/block/src/from-rpc.ts index 3169df0497..6891aa0492 100644 --- a/packages/block/src/from-rpc.ts +++ b/packages/block/src/from-rpc.ts @@ -1,5 +1,5 @@ import { TransactionFactory } from '@ethereumjs/tx' -import { TypeOutput, setLengthLeft, toBuffer, toType } from '@ethereumjs/util' +import { TypeOutput, setLengthLeft, toBytes, toType } from '@ethereumjs/util' import { blockHeaderFromRpc } from './header-from-rpc' @@ -21,7 +21,7 @@ function normalizeTxParams(_txParams: any) { // strict byte length checking txParams.to = txParams.to !== null && txParams.to !== undefined - ? setLengthLeft(toBuffer(txParams.to), 20) + ? setLengthLeft(toBytes(txParams.to), 20) : null txParams.v = toType(txParams.v, TypeOutput.BigInt) diff --git a/packages/block/src/header.ts b/packages/block/src/header.ts index 7f99a9200d..35905e0960 100644 --- a/packages/block/src/header.ts +++ b/packages/block/src/header.ts @@ -5,28 +5,31 @@ import { KECCAK256_RLP, KECCAK256_RLP_ARRAY, TypeOutput, - arrToBufArr, - bigIntToBuffer, + bigIntToBytes, bigIntToHex, - bigIntToUnpaddedBuffer, - bufArrToArr, - bufferToBigInt, - bufferToHex, + bigIntToUnpaddedBytes, + bytesToBigInt, + bytesToHex, + bytesToPrefixedHexString, + concatBytes, + concatBytesNoTypeCheck, ecrecover, ecsign, + equalsBytes, toType, zeros, } from '@ethereumjs/util' import { keccak256 } from 'ethereum-cryptography/keccak' +import { hexToBytes } from 'ethereum-cryptography/utils' import { CLIQUE_EXTRA_SEAL, CLIQUE_EXTRA_VANITY } from './clique' import { valuesArrayToHeaderData } from './helpers' -import type { BlockHeaderBuffer, BlockOptions, HeaderData, JsonHeader } from './types' +import type { BlockHeaderBytes, BlockOptions, HeaderData, JsonHeader } from './types' import type { CliqueConfig } from '@ethereumjs/common' interface HeaderCache { - hash: Buffer | undefined + hash: Uint8Array | undefined } const DEFAULT_GAS_LIMIT = BigInt('0xffffffffffffff') @@ -35,23 +38,23 @@ const DEFAULT_GAS_LIMIT = BigInt('0xffffffffffffff') * An object that represents the block header. */ export class BlockHeader { - public readonly parentHash: Buffer - public readonly uncleHash: Buffer + public readonly parentHash: Uint8Array + public readonly uncleHash: Uint8Array public readonly coinbase: Address - public readonly stateRoot: Buffer - public readonly transactionsTrie: Buffer - public readonly receiptTrie: Buffer - public readonly logsBloom: Buffer + public readonly stateRoot: Uint8Array + public readonly transactionsTrie: Uint8Array + public readonly receiptTrie: Uint8Array + public readonly logsBloom: Uint8Array public readonly difficulty: bigint public readonly number: bigint public readonly gasLimit: bigint public readonly gasUsed: bigint public readonly timestamp: bigint - public readonly extraData: Buffer - public readonly mixHash: Buffer - public readonly nonce: Buffer + public readonly extraData: Uint8Array + public readonly mixHash: Uint8Array + public readonly nonce: Uint8Array public readonly baseFeePerGas?: bigint - public readonly withdrawalsRoot?: Buffer + public readonly withdrawalsRoot?: Uint8Array public readonly excessDataGas?: bigint public readonly _common: Common @@ -89,28 +92,28 @@ export class BlockHeader { * @param serializedHeaderData * @param opts */ - public static fromRLPSerializedHeader(serializedHeaderData: Buffer, opts: BlockOptions = {}) { - const values = arrToBufArr(RLP.decode(Uint8Array.from(serializedHeaderData))) + public static fromRLPSerializedHeader(serializedHeaderData: Uint8Array, opts: BlockOptions = {}) { + const values = RLP.decode(serializedHeaderData) if (!Array.isArray(values)) { throw new Error('Invalid serialized header input. Must be array') } - return BlockHeader.fromValuesArray(values as Buffer[], opts) + return BlockHeader.fromValuesArray(values as Uint8Array[], opts) } /** - * Static constructor to create a block header from an array of Buffer values + * Static constructor to create a block header from an array of Bytes values * * @param values * @param opts */ - public static fromValuesArray(values: BlockHeaderBuffer, opts: BlockOptions = {}) { + public static fromValuesArray(values: BlockHeaderBytes, opts: BlockOptions = {}) { const headerData = valuesArrayToHeaderData(values) const { number, baseFeePerGas } = headerData // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions if (opts.common?.isActivatedEIP(1559) && baseFeePerGas === undefined) { - const eip1559ActivationBlock = bigIntToBuffer(opts.common?.eipBlock(1559)!) + const eip1559ActivationBlock = bigIntToBytes(opts.common?.eipBlock(1559)!) // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions - if (eip1559ActivationBlock && eip1559ActivationBlock.equals(number! as Buffer)) { + if (eip1559ActivationBlock && equalsBytes(eip1559ActivationBlock, number as Uint8Array)) { throw new Error('invalid header. baseFeePerGas should be provided') } } @@ -153,29 +156,30 @@ export class BlockHeader { gasLimit: DEFAULT_GAS_LIMIT, gasUsed: BigInt(0), timestamp: BigInt(0), - extraData: Buffer.from([]), + extraData: new Uint8Array(0), mixHash: zeros(32), nonce: zeros(8), } - const parentHash = toType(headerData.parentHash, TypeOutput.Buffer) ?? defaults.parentHash - const uncleHash = toType(headerData.uncleHash, TypeOutput.Buffer) ?? defaults.uncleHash + const parentHash = toType(headerData.parentHash, TypeOutput.Uint8Array) ?? defaults.parentHash + const uncleHash = toType(headerData.uncleHash, TypeOutput.Uint8Array) ?? defaults.uncleHash const coinbase = new Address( - toType(headerData.coinbase ?? defaults.coinbase, TypeOutput.Buffer) + toType(headerData.coinbase ?? defaults.coinbase, TypeOutput.Uint8Array) ) - const stateRoot = toType(headerData.stateRoot, TypeOutput.Buffer) ?? defaults.stateRoot + const stateRoot = toType(headerData.stateRoot, TypeOutput.Uint8Array) ?? defaults.stateRoot const transactionsTrie = - toType(headerData.transactionsTrie, TypeOutput.Buffer) ?? defaults.transactionsTrie - const receiptTrie = toType(headerData.receiptTrie, TypeOutput.Buffer) ?? defaults.receiptTrie - const logsBloom = toType(headerData.logsBloom, TypeOutput.Buffer) ?? defaults.logsBloom + toType(headerData.transactionsTrie, TypeOutput.Uint8Array) ?? defaults.transactionsTrie + const receiptTrie = + toType(headerData.receiptTrie, TypeOutput.Uint8Array) ?? defaults.receiptTrie + const logsBloom = toType(headerData.logsBloom, TypeOutput.Uint8Array) ?? defaults.logsBloom const difficulty = toType(headerData.difficulty, TypeOutput.BigInt) ?? defaults.difficulty const number = toType(headerData.number, TypeOutput.BigInt) ?? defaults.number const gasLimit = toType(headerData.gasLimit, TypeOutput.BigInt) ?? defaults.gasLimit const gasUsed = toType(headerData.gasUsed, TypeOutput.BigInt) ?? defaults.gasUsed const timestamp = toType(headerData.timestamp, TypeOutput.BigInt) ?? defaults.timestamp - const extraData = toType(headerData.extraData, TypeOutput.Buffer) ?? defaults.extraData - const mixHash = toType(headerData.mixHash, TypeOutput.Buffer) ?? defaults.mixHash - const nonce = toType(headerData.nonce, TypeOutput.Buffer) ?? defaults.nonce + const extraData = toType(headerData.extraData, TypeOutput.Uint8Array) ?? defaults.extraData + const mixHash = toType(headerData.mixHash, TypeOutput.Uint8Array) ?? defaults.mixHash + const nonce = toType(headerData.nonce, TypeOutput.Uint8Array) ?? defaults.nonce const hardforkByBlockNumber = options.hardforkByBlockNumber ?? false if (hardforkByBlockNumber || options.hardforkByTTD !== undefined) { @@ -196,7 +200,7 @@ export class BlockHeader { const baseFeePerGas = toType(headerData.baseFeePerGas, TypeOutput.BigInt) ?? hardforkDefaults.baseFeePerGas const withdrawalsRoot = - toType(headerData.withdrawalsRoot, TypeOutput.Buffer) ?? hardforkDefaults.withdrawalsRoot + toType(headerData.withdrawalsRoot, TypeOutput.Uint8Array) ?? hardforkDefaults.withdrawalsRoot const excessDataGas = toType(headerData.excessDataGas, TypeOutput.BigInt) ?? hardforkDefaults.excessDataGas @@ -251,7 +255,7 @@ export class BlockHeader { const minExtraDataLength = CLIQUE_EXTRA_VANITY + CLIQUE_EXTRA_SEAL if (this.extraData.length < minExtraDataLength) { const remainingLength = minExtraDataLength - this.extraData.length - this.extraData = Buffer.concat([this.extraData, Buffer.alloc(remainingLength)]) + this.extraData = concatBytes(this.extraData, new Uint8Array(remainingLength)) } this.extraData = this.cliqueSealBlock(options.cliqueSigner) @@ -390,7 +394,7 @@ export class BlockHeader { } } // MixHash format - if (!this.mixHash.equals(Buffer.alloc(32))) { + if (!equalsBytes(this.mixHash, new Uint8Array(32))) { const msg = this._errorMsg(`mixHash must be filled with zeros, received ${this.mixHash}`) throw new Error(msg) } @@ -400,10 +404,10 @@ export class BlockHeader { let error = false let errorMsg = '' - if (!uncleHash.equals(KECCAK256_RLP_ARRAY)) { - errorMsg += `, uncleHash: ${uncleHash.toString( - 'hex' - )} (expected: ${KECCAK256_RLP_ARRAY.toString('hex')})` + if (!equalsBytes(uncleHash, KECCAK256_RLP_ARRAY)) { + errorMsg += `, uncleHash: ${bytesToHex(uncleHash)} (expected: ${bytesToHex( + KECCAK256_RLP_ARRAY + )})` error = true } if (number !== BigInt(0)) { @@ -413,18 +417,18 @@ export class BlockHeader { error = true } if (extraData.length > 32) { - errorMsg += `, extraData: ${extraData.toString( - 'hex' + errorMsg += `, extraData: ${bytesToHex( + extraData )} (cannot exceed 32 bytes length, received ${extraData.length} bytes)` error = true } - if (!nonce.equals(zeros(8))) { - errorMsg += `, nonce: ${nonce.toString('hex')} (expected: ${zeros(8).toString('hex')})` + if (!equalsBytes(nonce, zeros(8))) { + errorMsg += `, nonce: ${bytesToHex(nonce)} (expected: ${bytesToHex(zeros(8))})` error = true } } if (error) { - const msg = this._errorMsg(`Invalid PoS block${errorMsg}`) + const msg = this._errorMsg(`Invalid PoS block: ${errorMsg}`) throw new Error(msg) } } @@ -520,36 +524,36 @@ export class BlockHeader { } /** - * Returns a Buffer Array of the raw Buffers in this header, in order. + * Returns a Uint8Array Array of the raw Bytes in this header, in order. */ - raw(): BlockHeaderBuffer { + raw(): BlockHeaderBytes { const rawItems = [ this.parentHash, this.uncleHash, - this.coinbase.buf, + this.coinbase.bytes, this.stateRoot, this.transactionsTrie, this.receiptTrie, this.logsBloom, - bigIntToUnpaddedBuffer(this.difficulty), - bigIntToUnpaddedBuffer(this.number), - bigIntToUnpaddedBuffer(this.gasLimit), - bigIntToUnpaddedBuffer(this.gasUsed), - bigIntToUnpaddedBuffer(this.timestamp ?? BigInt(0)), + bigIntToUnpaddedBytes(this.difficulty), + bigIntToUnpaddedBytes(this.number), + bigIntToUnpaddedBytes(this.gasLimit), + bigIntToUnpaddedBytes(this.gasUsed), + bigIntToUnpaddedBytes(this.timestamp ?? BigInt(0)), this.extraData, this.mixHash, this.nonce, ] if (this._common.isActivatedEIP(1559) === true) { - rawItems.push(bigIntToUnpaddedBuffer(this.baseFeePerGas!)) + rawItems.push(bigIntToUnpaddedBytes(this.baseFeePerGas!)) } if (this._common.isActivatedEIP(4895) === true) { rawItems.push(this.withdrawalsRoot!) } if (this._common.isActivatedEIP(4844) === true) { - rawItems.push(bigIntToUnpaddedBuffer(this.excessDataGas!)) + rawItems.push(bigIntToUnpaddedBytes(this.excessDataGas!)) } return rawItems @@ -558,15 +562,15 @@ export class BlockHeader { /** * Returns the hash of the block header. */ - hash(): Buffer { + hash(): Uint8Array { if (Object.isFrozen(this)) { if (!this.cache.hash) { - this.cache.hash = Buffer.from(keccak256(RLP.encode(bufArrToArr(this.raw())))) + this.cache.hash = keccak256(RLP.encode(this.raw())) } return this.cache.hash } - return Buffer.from(keccak256(RLP.encode(bufArrToArr(this.raw())))) + return keccak256(RLP.encode(this.raw())) } /** @@ -614,7 +618,7 @@ export class BlockHeader { if (this._common.hardforkGteHardfork(hardfork, Hardfork.Byzantium) === true) { // max((2 if len(parent.uncles) else 1) - ((timestamp - parent.timestamp) // 9), -99) (EIP100) - const uncleAddend = parentBlockHeader.uncleHash.equals(KECCAK256_RLP_ARRAY) ? 1 : 2 + const uncleAddend = equalsBytes(parentBlockHeader.uncleHash, KECCAK256_RLP_ARRAY) ? 1 : 2 let a = BigInt(uncleAddend) - (blockTs - parentTs) / BigInt(9) const cutoff = BigInt(-99) // MAX(cutoff, a) @@ -666,8 +670,8 @@ export class BlockHeader { cliqueSigHash() { this._requireClique('cliqueSigHash') const raw = this.raw() - raw[12] = this.extraData.slice(0, this.extraData.length - CLIQUE_EXTRA_SEAL) - return Buffer.from(keccak256(RLP.encode(bufArrToArr(raw)))) + raw[12] = this.extraData.subarray(0, this.extraData.length - CLIQUE_EXTRA_SEAL) + return keccak256(RLP.encode(raw)) } /** @@ -686,18 +690,18 @@ export class BlockHeader { * Returns extra vanity data * (only clique PoA, throws otherwise) */ - cliqueExtraVanity(): Buffer { + cliqueExtraVanity(): Uint8Array { this._requireClique('cliqueExtraVanity') - return this.extraData.slice(0, CLIQUE_EXTRA_VANITY) + return this.extraData.subarray(0, CLIQUE_EXTRA_VANITY) } /** * Returns extra seal data * (only clique PoA, throws otherwise) */ - cliqueExtraSeal(): Buffer { + cliqueExtraSeal(): Uint8Array { this._requireClique('cliqueExtraSeal') - return this.extraData.slice(-CLIQUE_EXTRA_SEAL) + return this.extraData.subarray(-CLIQUE_EXTRA_SEAL) } /** @@ -705,18 +709,21 @@ export class BlockHeader { * Returns the final extraData field to be assigned to `this.extraData`. * @hidden */ - private cliqueSealBlock(privateKey: Buffer) { + private cliqueSealBlock(privateKey: Uint8Array) { this._requireClique('cliqueSealBlock') const signature = ecsign(this.cliqueSigHash(), privateKey) - const signatureB = Buffer.concat([ + const signatureB = concatBytesNoTypeCheck( signature.r, signature.s, - bigIntToBuffer(signature.v - BigInt(27)), - ]) + bigIntToBytes(signature.v - BigInt(27)) + ) - const extraDataWithoutSeal = this.extraData.slice(0, this.extraData.length - CLIQUE_EXTRA_SEAL) - const extraData = Buffer.concat([extraDataWithoutSeal, signatureB]) + const extraDataWithoutSeal = this.extraData.subarray( + 0, + this.extraData.length - CLIQUE_EXTRA_SEAL + ) + const extraData = concatBytesNoTypeCheck(extraDataWithoutSeal, signatureB) return extraData } @@ -737,12 +744,12 @@ export class BlockHeader { const start = CLIQUE_EXTRA_VANITY const end = this.extraData.length - CLIQUE_EXTRA_SEAL - const signerBuffer = this.extraData.slice(start, end) + const signerBytes = this.extraData.subarray(start, end) - const signerList: Buffer[] = [] + const signerList: Uint8Array[] = [] const signerLength = 20 - for (let start = 0; start <= signerBuffer.length - signerLength; start += signerLength) { - signerList.push(signerBuffer.slice(start, start + signerLength)) + for (let start = 0; start <= signerBytes.length - signerLength; start += signerLength) { + signerList.push(signerBytes.subarray(start, start + signerLength)) } return signerList.map((buf) => new Address(buf)) } @@ -769,12 +776,12 @@ export class BlockHeader { this._requireClique('cliqueSigner') const extraSeal = this.cliqueExtraSeal() // Reasonable default for default blocks - if (extraSeal.length === 0 || extraSeal.equals(Buffer.alloc(65).fill(0))) { + if (extraSeal.length === 0 || equalsBytes(extraSeal, new Uint8Array(65))) { return Address.zero() } - const r = extraSeal.slice(0, 32) - const s = extraSeal.slice(32, 64) - const v = bufferToBigInt(extraSeal.slice(64, 65)) + BigInt(27) + const r = extraSeal.subarray(0, 32) + const s = extraSeal.subarray(32, 64) + const v = bytesToBigInt(extraSeal.subarray(64, 65)) + BigInt(27) const pubKey = ecrecover(this.cliqueSigHash(), v, r, s) return Address.fromPublicKey(pubKey) } @@ -782,8 +789,8 @@ export class BlockHeader { /** * Returns the rlp encoding of the block header. */ - serialize(): Buffer { - return Buffer.from(RLP.encode(bufArrToArr(this.raw()))) + serialize(): Uint8Array { + return RLP.encode(this.raw()) } /** @@ -791,25 +798,25 @@ export class BlockHeader { */ toJSON(): JsonHeader { const withdrawalAttr = this.withdrawalsRoot - ? { withdrawalsRoot: '0x' + this.withdrawalsRoot.toString('hex') } + ? { withdrawalsRoot: bytesToPrefixedHexString(this.withdrawalsRoot) } : {} const jsonDict: JsonHeader = { - parentHash: '0x' + this.parentHash.toString('hex'), - uncleHash: '0x' + this.uncleHash.toString('hex'), + parentHash: bytesToPrefixedHexString(this.parentHash), + uncleHash: bytesToPrefixedHexString(this.uncleHash), coinbase: this.coinbase.toString(), - stateRoot: '0x' + this.stateRoot.toString('hex'), - transactionsTrie: '0x' + this.transactionsTrie.toString('hex'), + stateRoot: bytesToPrefixedHexString(this.stateRoot), + transactionsTrie: bytesToPrefixedHexString(this.transactionsTrie), ...withdrawalAttr, - receiptTrie: '0x' + this.receiptTrie.toString('hex'), - logsBloom: '0x' + this.logsBloom.toString('hex'), + receiptTrie: bytesToPrefixedHexString(this.receiptTrie), + logsBloom: bytesToPrefixedHexString(this.logsBloom), difficulty: bigIntToHex(this.difficulty), number: bigIntToHex(this.number), gasLimit: bigIntToHex(this.gasLimit), gasUsed: bigIntToHex(this.gasUsed), timestamp: bigIntToHex(this.timestamp), - extraData: '0x' + this.extraData.toString('hex'), - mixHash: '0x' + this.mixHash.toString('hex'), - nonce: '0x' + this.nonce.toString('hex'), + extraData: bytesToPrefixedHexString(this.extraData), + mixHash: bytesToPrefixedHexString(this.mixHash), + nonce: bytesToPrefixedHexString(this.nonce), } if (this._common.isActivatedEIP(1559) === true) { jsonDict.baseFeePerGas = bigIntToHex(this.baseFeePerGas!) @@ -832,10 +839,10 @@ export class BlockHeader { if (DAOActivationBlock === null || this.number < DAOActivationBlock) { return } - const DAO_ExtraData = Buffer.from('64616f2d686172642d666f726b', 'hex') + const DAO_ExtraData = hexToBytes('64616f2d686172642d666f726b') const DAO_ForceExtraDataRange = BigInt(9) const drift = this.number - DAOActivationBlock - if (drift <= DAO_ForceExtraDataRange && !this.extraData.equals(DAO_ExtraData)) { + if (drift <= DAO_ForceExtraDataRange && !equalsBytes(this.extraData, DAO_ExtraData)) { const msg = this._errorMsg("extraData should be 'dao-hard-fork'") throw new Error(msg) } @@ -847,7 +854,7 @@ export class BlockHeader { public errorStr() { let hash = '' try { - hash = bufferToHex(this.hash()) + hash = bytesToHex(this.hash()) } catch (e: any) { hash = 'error' } diff --git a/packages/block/src/helpers.ts b/packages/block/src/helpers.ts index a89a35cc5d..8c3fcd4dab 100644 --- a/packages/block/src/helpers.ts +++ b/packages/block/src/helpers.ts @@ -1,7 +1,7 @@ import { TypeOutput, isHexString, toType } from '@ethereumjs/util' import type { BlockHeader } from './header' -import type { BlockHeaderBuffer, HeaderData } from './types' +import type { BlockHeaderBytes, HeaderData } from './types' /** * Returns a 0x-prefixed hex number string from a hex string or string integer. @@ -20,7 +20,7 @@ export const numberToHex = function (input?: string) { return input } -export function valuesArrayToHeaderData(values: BlockHeaderBuffer): HeaderData { +export function valuesArrayToHeaderData(values: BlockHeaderBytes): HeaderData { const [ parentHash, uncleHash, diff --git a/packages/block/src/types.ts b/packages/block/src/types.ts index 1fa494f2bf..3fe11f549c 100644 --- a/packages/block/src/types.ts +++ b/packages/block/src/types.ts @@ -10,9 +10,9 @@ import type { import type { AddressLike, BigIntLike, - BufferLike, + BytesLike, JsonRpcWithdrawal, - WithdrawalBuffer, + WithdrawalBytes, WithdrawalData, } from '@ethereumjs/util' @@ -76,7 +76,7 @@ export interface BlockOptions { * Provide a clique signer's privateKey to seal this block. * Will throw if provided on a non-PoA chain. */ - cliqueSigner?: Buffer + cliqueSigner?: Uint8Array /** * Skip consensus format validation checks on header if set. Defaults to false. */ @@ -87,23 +87,23 @@ export interface BlockOptions { * A block header's data. */ export interface HeaderData { - parentHash?: BufferLike - uncleHash?: BufferLike + parentHash?: BytesLike + uncleHash?: BytesLike coinbase?: AddressLike - stateRoot?: BufferLike - transactionsTrie?: BufferLike - receiptTrie?: BufferLike - logsBloom?: BufferLike + stateRoot?: BytesLike + transactionsTrie?: BytesLike + receiptTrie?: BytesLike + logsBloom?: BytesLike difficulty?: BigIntLike number?: BigIntLike gasLimit?: BigIntLike gasUsed?: BigIntLike timestamp?: BigIntLike - extraData?: BufferLike - mixHash?: BufferLike - nonce?: BufferLike + extraData?: BytesLike + mixHash?: BytesLike + nonce?: BytesLike baseFeePerGas?: BigIntLike - withdrawalsRoot?: BufferLike + withdrawalsRoot?: BytesLike excessDataGas?: BigIntLike } @@ -120,18 +120,18 @@ export interface BlockData { withdrawals?: Array } -export type WithdrawalsBuffer = WithdrawalBuffer[] +export type WithdrawalsBytes = WithdrawalBytes[] -export type BlockBuffer = - | [BlockHeaderBuffer, TransactionsBuffer, UncleHeadersBuffer] - | [BlockHeaderBuffer, TransactionsBuffer, UncleHeadersBuffer, WithdrawalsBuffer] -export type BlockHeaderBuffer = Buffer[] -export type BlockBodyBuffer = [TransactionsBuffer, UncleHeadersBuffer, WithdrawalsBuffer?] +export type BlockBytes = + | [BlockHeaderBytes, TransactionsBytes, UncleHeadersBytes] + | [BlockHeaderBytes, TransactionsBytes, UncleHeadersBytes, WithdrawalsBytes] +export type BlockHeaderBytes = Uint8Array[] +export type BlockBodyBytes = [TransactionsBytes, UncleHeadersBytes, WithdrawalsBytes?] /** - * TransactionsBuffer can be an array of serialized txs for Typed Transactions or an array of Buffer Arrays for legacy transactions. + * TransactionsBytes can be an array of serialized txs for Typed Transactions or an array of Uint8Array Arrays for legacy transactions. */ -export type TransactionsBuffer = Buffer[][] | Buffer[] -export type UncleHeadersBuffer = Buffer[][] +export type TransactionsBytes = Uint8Array[][] | Uint8Array[] +export type UncleHeadersBytes = Uint8Array[][] /** * An object with the block's data represented as strings. diff --git a/packages/block/test/block.spec.ts b/packages/block/test/block.spec.ts index e7e6a3a73e..9857da8272 100644 --- a/packages/block/test/block.spec.ts +++ b/packages/block/test/block.spec.ts @@ -1,6 +1,6 @@ import { Chain, Common, Hardfork } from '@ethereumjs/common' import { RLP } from '@ethereumjs/rlp' -import { toBuffer, zeros } from '@ethereumjs/util' +import { bytesToHex, equalsBytes, hexStringToBytes, toBytes, zeros } from '@ethereumjs/util' import * as tape from 'tape' // explicitly import util, needed for karma-typescript bundling // eslint-disable-next-line @typescript-eslint/no-unused-vars, simple-import-sort/imports @@ -15,14 +15,14 @@ import * as testDataPreLondon2 from './testdata/testdata_pre-london-2.json' import * as testDataPreLondon from './testdata/testdata_pre-london.json' import * as testnetMerge from './testdata/testnetMerge.json' -import type { BlockBuffer } from '../src' +import type { BlockBytes } from '../src' import type { NestedUint8Array } from '@ethereumjs/util' tape('[Block]: block functions', function (t) { t.test('should test block initialization', function (st) { const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Chainstart }) const genesis = Block.fromBlockData({}, { common }) - st.ok(genesis.hash().toString('hex'), 'block should initialize') + st.ok(bytesToHex(genesis.hash()), 'block should initialize') // test default freeze values // also test if the options are carried over to the constructor @@ -39,22 +39,22 @@ tape('[Block]: block functions', function (t) { block = Block.fromRLPSerializedBlock(rlpBlock, { freeze: false }) st.ok(!Object.isFrozen(block), 'block should not be frozen when freeze deactivated in options') - const zero = Buffer.alloc(0) + const zero = new Uint8Array(0) const headerArray = [] for (let item = 0; item < 15; item++) { headerArray.push(zero) } // mock header data (if set to zeros(0) header throws) - headerArray[0] = zeros(32) //parentHash - headerArray[2] = zeros(20) //coinbase - headerArray[3] = zeros(32) //stateRoot - headerArray[4] = zeros(32) //transactionsTrie - headerArray[5] = zeros(32) //receiptTrie + headerArray[0] = zeros(32) // parentHash + headerArray[2] = zeros(20) // coinbase + headerArray[3] = zeros(32) // stateRoot + headerArray[4] = zeros(32) // transactionsTrie + headerArray[5] = zeros(32) // receiptTrie headerArray[13] = zeros(32) // mixHash headerArray[14] = zeros(8) // nonce - const valuesArray = [headerArray, [], []] + const valuesArray = [headerArray, [], []] block = Block.fromValuesArray(valuesArray, { common }) st.ok(Object.isFrozen(block), 'block should be frozen by default') @@ -77,7 +77,7 @@ tape('[Block]: block functions', function (t) { { header: { number: 12, // Berlin block - extraData: Buffer.alloc(97), + extraData: new Uint8Array(97), }, }, { common, hardforkByBlockNumber: true } @@ -102,7 +102,7 @@ tape('[Block]: block functions', function (t) { { header: { number: 12, // Berlin block, - extraData: Buffer.alloc(97), + extraData: new Uint8Array(97), }, }, { common, hardforkByTTD: 3000 } @@ -151,7 +151,7 @@ tape('[Block]: block functions', function (t) { function (st) { const common = new Common({ chain: Chain.Rinkeby }) const uncleBlock = Block.fromBlockData( - { header: { extraData: Buffer.alloc(117) } }, + { header: { extraData: new Uint8Array(117) } }, { common } ) st.throws(function () { @@ -163,7 +163,7 @@ tape('[Block]: block functions', function (t) { t.test('should test block validation on pow chain', async function (st) { const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Istanbul }) - const blockRlp = toBuffer(testDataPreLondon.blocks[0].rlp) + const blockRlp = toBytes(testDataPreLondon.blocks[0].rlp) try { Block.fromRLPSerializedBlock(blockRlp, { common }) st.pass('should pass') @@ -189,11 +189,11 @@ tape('[Block]: block functions', function (t) { } t.test('should test transaction validation', async function (st) { - const blockRlp = toBuffer(testDataPreLondon.blocks[0].rlp) + const blockRlp = toBytes(testDataPreLondon.blocks[0].rlp) const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.London }) const block = Block.fromRLPSerializedBlock(blockRlp, { common, freeze: false }) await testTransactionValidation(st, block) - ;(block.header as any).transactionsTrie = Buffer.alloc(32) + ;(block.header as any).transactionsTrie = new Uint8Array(32) try { await block.validateData() st.fail('should throw') @@ -209,7 +209,7 @@ tape('[Block]: block functions', function (t) { t.test('should test transaction validation with legacy tx in london', async function (st) { const common = new Common({ chain: Chain.Ropsten, hardfork: Hardfork.London }) - const blockRlp = toBuffer(testDataPreLondon.blocks[0].rlp) + const blockRlp = toBytes(testDataPreLondon.blocks[0].rlp) const block = Block.fromRLPSerializedBlock(blockRlp, { common, freeze: false }) await testTransactionValidation(st, block) ;(block.transactions[0] as any).gasPrice = BigInt(0) @@ -222,10 +222,10 @@ tape('[Block]: block functions', function (t) { t.test('should test uncles hash validation', async function (st) { const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Istanbul }) - const blockRlp = toBuffer(testDataPreLondon2.blocks[2].rlp) + const blockRlp = toBytes(testDataPreLondon2.blocks[2].rlp) const block = Block.fromRLPSerializedBlock(blockRlp, { common, freeze: false }) st.equal(block.validateUnclesHash(), true) - ;(block.header as any).uncleHash = Buffer.alloc(32) + ;(block.header as any).uncleHash = new Uint8Array(32) try { await block.validateData() st.fail('should throw') @@ -253,10 +253,10 @@ tape('[Block]: block functions', function (t) { t.test('should test genesis hashes (mainnet default)', function (st) { const common = new Common({ chain: Chain.Ropsten, hardfork: Hardfork.Chainstart }) - const rlp = Buffer.from(testDataGenesis.test.genesis_rlp_hex, 'hex') - const hash = Buffer.from(testDataGenesis.test.genesis_hash, 'hex') + const rlp = hexStringToBytes(testDataGenesis.test.genesis_rlp_hex) + const hash = hexStringToBytes(testDataGenesis.test.genesis_hash) const block = Block.fromRLPSerializedBlock(rlp, { common }) - st.ok(block.hash().equals(hash), 'genesis hash match') + st.ok(equalsBytes(block.hash(), hash), 'genesis hash match') st.end() }) @@ -272,17 +272,17 @@ tape('[Block]: block functions', function (t) { t.test('should return the same block data from raw()', function (st) { const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Istanbul }) - const block = Block.fromRLPSerializedBlock(toBuffer(testDataPreLondon2.blocks[2].rlp), { + const block = Block.fromRLPSerializedBlock(toBytes(testDataPreLondon2.blocks[2].rlp), { common, }) const blockFromRaw = Block.fromValuesArray(block.raw(), { common }) - st.ok(block.hash().equals(blockFromRaw.hash())) + st.ok(equalsBytes(block.hash(), blockFromRaw.hash())) st.end() }) t.test('should test toJSON', function (st) { const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Istanbul }) - const block = Block.fromRLPSerializedBlock(toBuffer(testDataPreLondon2.blocks[2].rlp), { + const block = Block.fromRLPSerializedBlock(toBytes(testDataPreLondon2.blocks[2].rlp), { common, }) st.equal(typeof block.toJSON(), 'object') @@ -292,22 +292,22 @@ tape('[Block]: block functions', function (t) { t.test('DAO hardfork', function (st) { const blockData = RLP.decode(testDataPreLondon2.blocks[0].rlp) as NestedUint8Array // Set block number from test block to mainnet DAO fork block 1920000 - blockData[0][8] = Buffer.from('1D4C00', 'hex') + blockData[0][8] = hexStringToBytes('1D4C00') const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Dao }) st.throws( function () { - Block.fromValuesArray(blockData as BlockBuffer, { common }) + Block.fromValuesArray(blockData as BlockBytes, { common }) }, /Error: extraData should be 'dao-hard-fork'/, 'should throw on DAO HF block with wrong extra data' ) // eslint-disable-line // Set extraData to dao-hard-fork - blockData[0][12] = Buffer.from('64616f2d686172642d666f726b', 'hex') + blockData[0][12] = hexStringToBytes('64616f2d686172642d666f726b') st.doesNotThrow(function () { - Block.fromValuesArray(blockData as BlockBuffer, { common }) + Block.fromValuesArray(blockData as BlockBytes, { common }) }, 'should not throw on DAO HF block with correct extra data') st.end() }) diff --git a/packages/block/test/clique.spec.ts b/packages/block/test/clique.spec.ts index 947a2c8c21..8ca4bdb09b 100644 --- a/packages/block/test/clique.spec.ts +++ b/packages/block/test/clique.spec.ts @@ -1,5 +1,5 @@ import { Chain, Common, Hardfork } from '@ethereumjs/common' -import { Address } from '@ethereumjs/util' +import { Address, hexStringToBytes } from '@ethereumjs/util' import * as tape from 'tape' import { BlockHeader } from '../src/header' @@ -13,44 +13,47 @@ tape('[Header]: Clique PoA Functionality', function (t) { header.cliqueIsEpochTransition() }, 'cliqueIsEpochTransition() -> should throw on PoW networks') - header = BlockHeader.fromHeaderData({ extraData: Buffer.alloc(97) }, { common }) + header = BlockHeader.fromHeaderData({ extraData: new Uint8Array(97) }, { common }) st.ok( header.cliqueIsEpochTransition(), 'cliqueIsEpochTransition() -> should indicate an epoch transition for the genesis block' ) - header = BlockHeader.fromHeaderData({ number: 1, extraData: Buffer.alloc(97) }, { common }) + header = BlockHeader.fromHeaderData({ number: 1, extraData: new Uint8Array(97) }, { common }) st.notOk( header.cliqueIsEpochTransition(), 'cliqueIsEpochTransition() -> should correctly identify a non-epoch block' ) st.deepEqual( header.cliqueExtraVanity(), - Buffer.alloc(32), + new Uint8Array(32), 'cliqueExtraVanity() -> should return correct extra vanity value' ) st.deepEqual( header.cliqueExtraSeal(), - Buffer.alloc(65), + new Uint8Array(65), 'cliqueExtraSeal() -> should return correct extra seal value' ) st.throws(() => { header.cliqueEpochTransitionSigners() }, 'cliqueEpochTransitionSigners() -> should throw on non-epch block') - header = BlockHeader.fromHeaderData({ number: 60000, extraData: Buffer.alloc(137) }, { common }) + header = BlockHeader.fromHeaderData( + { number: 60000, extraData: new Uint8Array(137) }, + { common } + ) st.ok( header.cliqueIsEpochTransition(), 'cliqueIsEpochTransition() -> should correctly identify an epoch block' ) st.deepEqual( header.cliqueExtraVanity(), - Buffer.alloc(32), + new Uint8Array(32), 'cliqueExtraVanity() -> should return correct extra vanity value' ) st.deepEqual( header.cliqueExtraSeal(), - Buffer.alloc(65), + new Uint8Array(65), 'cliqueExtraSeal() -> should return correct extra seal value' ) const msg = @@ -62,19 +65,17 @@ tape('[Header]: Clique PoA Functionality', function (t) { type Signer = { address: Address - privateKey: Buffer - publicKey: Buffer + privateKey: Uint8Array + publicKey: Uint8Array } const A: Signer = { - address: new Address(Buffer.from('0b90087d864e82a284dca15923f3776de6bb016f', 'hex')), - privateKey: Buffer.from( - '64bf9cc30328b0e42387b3c82c614e6386259136235e20c1357bd11cdee86993', - 'hex' + address: new Address(hexStringToBytes('0b90087d864e82a284dca15923f3776de6bb016f')), + privateKey: hexStringToBytes( + '64bf9cc30328b0e42387b3c82c614e6386259136235e20c1357bd11cdee86993' ), - publicKey: Buffer.from( - '40b2ebdf4b53206d2d3d3d59e7e2f13b1ea68305aec71d5d24cefe7f24ecae886d241f9267f04702d7f693655eb7b4aa23f30dcd0c3c5f2b970aad7c8a828195', - 'hex' + publicKey: hexStringToBytes( + '40b2ebdf4b53206d2d3d3d59e7e2f13b1ea68305aec71d5d24cefe7f24ecae886d241f9267f04702d7f693655eb7b4aa23f30dcd0c3c5f2b970aad7c8a828195' ), } @@ -82,7 +83,7 @@ tape('[Header]: Clique PoA Functionality', function (t) { const cliqueSigner = A.privateKey let header = BlockHeader.fromHeaderData( - { number: 1, extraData: Buffer.alloc(97) }, + { number: 1, extraData: new Uint8Array(97) }, { common, freeze: false, cliqueSigner } ) @@ -90,7 +91,7 @@ tape('[Header]: Clique PoA Functionality', function (t) { st.ok(header.cliqueVerifySignature([A.address]), 'should verify signature') st.ok(header.cliqueSigner().equals(A.address), 'should recover the correct signer address') - header = BlockHeader.fromHeaderData({ extraData: Buffer.alloc(97) }, { common }) + header = BlockHeader.fromHeaderData({ extraData: new Uint8Array(97) }, { common }) st.ok( header.cliqueSigner().equals(Address.zero()), 'should return zero address on default block' diff --git a/packages/block/test/difficulty.spec.ts b/packages/block/test/difficulty.spec.ts index 05cf8afdfa..c3b4fab6ac 100644 --- a/packages/block/test/difficulty.spec.ts +++ b/packages/block/test/difficulty.spec.ts @@ -1,5 +1,4 @@ import { Chain, Common } from '@ethereumjs/common' -import { bufferToInt } from '@ethereumjs/util' import * as tape from 'tape' import { Block } from '../src' @@ -112,7 +111,7 @@ tape('[Header]: difficulty tests', (t) => { header: { timestamp: test.parentTimestamp, difficulty: test.parentDifficulty, - number: bufferToInt(test.currentBlockNumber) - 1, + number: BigInt(test.currentBlockNumber) - BigInt(1), uncleHash, }, }, diff --git a/packages/block/test/eip1559block.spec.ts b/packages/block/test/eip1559block.spec.ts index 6942bc0a75..2384eb74d2 100644 --- a/packages/block/test/eip1559block.spec.ts +++ b/packages/block/test/eip1559block.spec.ts @@ -1,5 +1,6 @@ import { Chain, Common, Hardfork } from '@ethereumjs/common' import { FeeMarketEIP1559Transaction } from '@ethereumjs/tx' +import { hexStringToBytes } from '@ethereumjs/util' import * as tape from 'tape' import { Block } from '../src/block' @@ -168,7 +169,7 @@ tape('EIP1559 tests', function (t) { parentHash: block1.hash(), timestamp: BigInt(2), gasLimit: genesis.header.gasLimit * BigInt(2), // Special case on EIP-1559 transition block - baseFeePerGas: Buffer.from('342770c0', 'hex'), + baseFeePerGas: hexStringToBytes('342770c0'), }, }, { @@ -283,7 +284,7 @@ tape('EIP1559 tests', function (t) { parentHash: block1.hash(), timestamp: BigInt(2), gasLimit: parentGasLimit + parentGasLimit / BigInt(1024) - BigInt(1), - baseFeePerGas: Buffer.from('342770c0', 'hex'), + baseFeePerGas: hexStringToBytes('342770c0'), }, { calcDifficultyFromHeader: block1.header, @@ -299,7 +300,7 @@ tape('EIP1559 tests', function (t) { parentHash: block1.hash(), timestamp: BigInt(2), gasLimit: parentGasLimit - parentGasLimit / BigInt(1024) + BigInt(1), - baseFeePerGas: Buffer.from('342770c0', 'hex'), + baseFeePerGas: hexStringToBytes('342770c0'), }, { calcDifficultyFromHeader: block1.header, @@ -343,7 +344,7 @@ tape('EIP1559 tests', function (t) { parentHash: block1.hash(), timestamp: BigInt(2), gasLimit: parentGasLimit + parentGasLimit / BigInt(1024), - baseFeePerGas: Buffer.from('342770c0', 'hex'), + baseFeePerGas: hexStringToBytes('342770c0'), }, { calcDifficultyFromHeader: block1.header, @@ -394,7 +395,7 @@ tape('EIP1559 tests', function (t) { parentHash: block1.hash(), timestamp: BigInt(2), gasLimit: parentGasLimit - parentGasLimit / BigInt(1024), - baseFeePerGas: Buffer.from('342770c0', 'hex'), + baseFeePerGas: hexStringToBytes('342770c0'), }, { calcDifficultyFromHeader: block1.header, @@ -420,7 +421,7 @@ tape('EIP1559 tests', function (t) { maxPriorityFeePerGas: BigInt(0), }, { common } - ).sign(Buffer.from('46'.repeat(32), 'hex')) + ).sign(hexStringToBytes('46'.repeat(32))) const block = Block.fromBlockData( { header: { diff --git a/packages/block/test/eip4844block.spec.ts b/packages/block/test/eip4844block.spec.ts index 2d048de225..c38fe88738 100644 --- a/packages/block/test/eip4844block.spec.ts +++ b/packages/block/test/eip4844block.spec.ts @@ -5,8 +5,8 @@ import { commitmentsToVersionedHashes, getBlobs, } from '@ethereumjs/tx/dist/utils/blobHelpers' +import { randomBytes } from '@ethereumjs/util' import * as kzg from 'c-kzg' -import { randomBytes } from 'crypto' import * as tape from 'tape' import { Block, calcExcessDataGas, getDataGasPrice } from '../src' @@ -129,11 +129,9 @@ tape('data gas tests', async (t) => { const commitments = blobsToCommitments(blobs) const versionedHashes = commitmentsToVersionedHashes(commitments) - const bufferedHashes = versionedHashes.map((el) => Buffer.from(el)) - const unsignedTx = BlobEIP4844Transaction.fromTxData( { - versionedHashes: bufferedHashes, + versionedHashes, blobs, kzgCommitments: commitments, maxFeePerDataGas: 100000000n, @@ -161,11 +159,9 @@ tape('transaction validation tests', async (t) => { const commitments = blobsToCommitments(blobs) const versionedHashes = commitmentsToVersionedHashes(commitments) - const bufferedHashes = versionedHashes.map((el) => Buffer.from(el)) - const tx1 = BlobEIP4844Transaction.fromTxData( { - versionedHashes: bufferedHashes, + versionedHashes, blobs, kzgCommitments: commitments, maxFeePerDataGas: 100000000n, @@ -176,7 +172,7 @@ tape('transaction validation tests', async (t) => { ).sign(randomBytes(32)) const tx2 = BlobEIP4844Transaction.fromTxData( { - versionedHashes: bufferedHashes, + versionedHashes, blobs, kzgCommitments: commitments, maxFeePerDataGas: 1n, diff --git a/packages/block/test/eip4895block.spec.ts b/packages/block/test/eip4895block.spec.ts index 32245cc8a0..9a4912ad5b 100644 --- a/packages/block/test/eip4895block.spec.ts +++ b/packages/block/test/eip4895block.spec.ts @@ -1,12 +1,12 @@ import { Chain, Common, Hardfork } from '@ethereumjs/common' import { RLP } from '@ethereumjs/rlp' -import { Address, KECCAK256_RLP, Withdrawal } from '@ethereumjs/util' +import { Address, KECCAK256_RLP, Withdrawal, hexStringToBytes } from '@ethereumjs/util' import * as tape from 'tape' import { Block } from '../src/block' import { BlockHeader } from '../src/header' -import type { WithdrawalBuffer, WithdrawalData } from '@ethereumjs/util' +import type { WithdrawalBytes, WithdrawalData } from '@ethereumjs/util' const gethWithdrawals8BlockRlp = 'f903e1f90213a0fe950635b1bd2a416ff6283b0bbd30176e1b1125ad06fa729da9f3f4c1c61710a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794aa00000000000000000000000000000000000000a07f7510a0cb6203f456e34ec3e2ce30d6c5590ded42c10a9cf3f24784119c5afba056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080018401c9c380802f80a0ff0000000000000000000000000000000000000000000000000000000000000088000000000000000007a0b695b29ec7ee934ef6a68838b13729f2d49fffe26718de16a1a9ed94a4d7d06dc0c0f901c6da8082ffff94000000000000000000000000000000000000000080f83b0183010000940100000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f83b0283010001940200000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f83b0383010002940300000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f83b0483010003940400000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f83b0583010004940500000000000000000000000000000000000000a00500000000000000000000000000000000000000000000000000000000000000f83b0683010005940600000000000000000000000000000000000000a00600000000000000000000000000000000000000000000000000000000000000f83b0783010006940700000000000000000000000000000000000000a00700000000000000000000000000000000000000000000000000000000000000' @@ -31,12 +31,12 @@ common.hardforkBlock = function (hardfork: string | undefined) { tape('EIP4895 tests', function (t) { t.test('should correctly generate withdrawalsRoot', async function (st) { // get withdwalsArray - const gethBlockBufferArray = RLP.decode(Buffer.from(gethWithdrawals8BlockRlp, 'hex')) - const withdrawals = (gethBlockBufferArray[3] as WithdrawalBuffer[]).map((wa) => + const gethBlockBytesArray = RLP.decode(hexStringToBytes(gethWithdrawals8BlockRlp)) + const withdrawals = (gethBlockBytesArray[3] as WithdrawalBytes[]).map((wa) => Withdrawal.fromValuesArray(wa) ) st.equal(withdrawals.length, 8, '8 withdrawals should have been found') - const gethWitdrawalsRoot = (gethBlockBufferArray[0] as Buffer[])[16] as Buffer + const gethWitdrawalsRoot = (gethBlockBytesArray[0] as Uint8Array[])[16] as Uint8Array st.deepEqual( await Block.genWithdrawalsTrieRoot(withdrawals), gethWitdrawalsRoot, @@ -50,7 +50,7 @@ tape('EIP4895 tests', function (t) { st.throws(() => { BlockHeader.fromHeaderData( { - withdrawalsRoot: Buffer.from('00'.repeat(32), 'hex'), + withdrawalsRoot: hexStringToBytes('00'.repeat(32)), }, { common: earlyCommon, @@ -68,7 +68,7 @@ tape('EIP4895 tests', function (t) { st.doesNotThrow(() => { BlockHeader.fromHeaderData( { - withdrawalsRoot: Buffer.from('00'.repeat(32), 'hex'), + withdrawalsRoot: hexStringToBytes('00'.repeat(32)), }, { common, @@ -101,7 +101,7 @@ tape('EIP4895 tests', function (t) { Block.fromBlockData( { header: { - withdrawalsRoot: Buffer.from('00'.repeat(32), 'hex'), + withdrawalsRoot: hexStringToBytes('00'.repeat(32)), }, withdrawals: [], }, @@ -113,7 +113,7 @@ tape('EIP4895 tests', function (t) { const block = Block.fromBlockData( { header: { - withdrawalsRoot: Buffer.from('00'.repeat(32), 'hex'), + withdrawalsRoot: hexStringToBytes('00'.repeat(32)), }, withdrawals: [], }, @@ -142,16 +142,15 @@ tape('EIP4895 tests', function (t) { const withdrawal = { index: BigInt(0), validatorIndex: BigInt(0), - address: new Address(Buffer.from('20'.repeat(20), 'hex')), + address: new Address(hexStringToBytes('20'.repeat(20))), amount: BigInt(1000), } const validBlockWithWithdrawal = Block.fromBlockData( { header: { - withdrawalsRoot: Buffer.from( - '897ca49edcb278aecab2688bcc2b7b7ee43524cc489672534fee332a172f1718', - 'hex' + withdrawalsRoot: hexStringToBytes( + '897ca49edcb278aecab2688bcc2b7b7ee43524cc489672534fee332a172f1718' ), }, withdrawals: [withdrawal], @@ -168,16 +167,15 @@ tape('EIP4895 tests', function (t) { const withdrawal2 = { index: BigInt(1), validatorIndex: BigInt(11), - address: new Address(Buffer.from('30'.repeat(20), 'hex')), + address: new Address(hexStringToBytes('30'.repeat(20))), amount: BigInt(2000), } const validBlockWithWithdrawal2 = Block.fromBlockData( { header: { - withdrawalsRoot: Buffer.from( - '3b514862c42008079d461392e29d5b6775dd5ed370a6c4441ccb8ab742bf2436', - 'hex' + withdrawalsRoot: hexStringToBytes( + '3b514862c42008079d461392e29d5b6775dd5ed370a6c4441ccb8ab742bf2436' ), }, withdrawals: [withdrawal, withdrawal2], @@ -208,7 +206,7 @@ tape('EIP4895 tests', function (t) { const rlpWithoutWithdrawals = RLP.encode(rlpDecoded.slice(0, 3)) // throw check if withdrawals array is not provided in the rlp st.throws(() => { - Block.fromRLPSerializedBlock(Buffer.from(rlpWithoutWithdrawals), { common }) + Block.fromRLPSerializedBlock(rlpWithoutWithdrawals, { common }) }, 'should provide withdrawals array when 4895 is active') st.end() }) diff --git a/packages/block/test/from-rpc.spec.ts b/packages/block/test/from-rpc.spec.ts index e17d1beb7f..e5d17cbde8 100644 --- a/packages/block/test/from-rpc.spec.ts +++ b/packages/block/test/from-rpc.spec.ts @@ -1,4 +1,6 @@ import { Chain, Common, Hardfork } from '@ethereumjs/common' +import { bytesToPrefixedHexString, hexStringToBytes } from '@ethereumjs/util' +import { bytesToHex, equalsBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' import { blockFromRpc } from '../src/from-rpc' @@ -32,8 +34,8 @@ tape('[fromRPC]: block #2924874', function (t) { t.test('should create a block header with the correct hash', function (st) { const block = blockHeaderFromRpc(blockData, { common }) - const hash = Buffer.from(blockData.hash.slice(2), 'hex') - st.ok(block.hash().equals(hash)) + const hash = hexStringToBytes(blockData.hash) + st.ok(equalsBytes(block.hash(), hash)) st.end() }) }) @@ -103,7 +105,7 @@ tape('[fromRPC]:', function (t) { `0x${block.header.baseFeePerGas?.toString(16)}`, testDataFromRpcGoerliLondon.baseFeePerGas ) - st.equal(`0x${block.hash().toString('hex')}`, testDataFromRpcGoerliLondon.hash) + st.equal(bytesToPrefixedHexString(block.hash()), testDataFromRpcGoerliLondon.hash) st.end() }) @@ -126,8 +128,8 @@ tape('[fromRPC]:', function (t) { function (st) { const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Shanghai }) const block = blockHeaderFromRpc(blockDataWithWithdrawals, { common }) - const hash = Buffer.from(blockDataWithWithdrawals.hash.slice(2), 'hex') - st.ok(block.hash().equals(hash)) + const hash = blockDataWithWithdrawals.hash.slice(2) + st.equal(bytesToHex(block.hash()), hash) st.end() } ) @@ -137,7 +139,7 @@ tape('[fromRPC] - Alchemy/Infura API block responses', (t) => { t.test('should create pre merge block from Alchemy API response to eth_getBlockByHash', (st) => { const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.London }) const block = blockFromRpc(alchemy14151203, [], { common }) - st.equal(`0x${block.hash().toString('hex')}`, alchemy14151203.hash) + st.equal(bytesToPrefixedHexString(block.hash()), alchemy14151203.hash) st.end() }) @@ -147,13 +149,13 @@ tape('[fromRPC] - Alchemy/Infura API block responses', (t) => { const common = new Common({ chain: Chain.Mainnet }) let block = blockFromRpc(infura2000004woTxs, [], { common, hardforkByBlockNumber: true }) st.equal( - `0x${block.hash().toString('hex')}`, + bytesToPrefixedHexString(block.hash()), infura2000004woTxs.hash, 'created premerge block w/o txns' ) block = blockFromRpc(infura2000004wTxs, [], { common, hardforkByBlockNumber: true }) st.equal( - `0x${block.hash().toString('hex')}`, + bytesToPrefixedHexString(block.hash()), infura2000004wTxs.hash, 'created premerge block with txns' ) @@ -162,7 +164,7 @@ tape('[fromRPC] - Alchemy/Infura API block responses', (t) => { hardforkByTTD: 58750000000000000000000n, }) st.equal( - `0x${block.hash().toString('hex')}`, + bytesToPrefixedHexString(block.hash()), infura15571241woTxs.hash, 'created post merge block without txns' ) @@ -172,7 +174,7 @@ tape('[fromRPC] - Alchemy/Infura API block responses', (t) => { hardforkByTTD: 58750000000000000000000n, }) st.equal( - `0x${block.hash().toString('hex')}`, + bytesToPrefixedHexString(block.hash()), infura15571241wTxs.hash, 'created post merge block with txns' ) @@ -189,7 +191,7 @@ tape('[fromEthersProvider]', async (t) => { const blockHash = '0x1850b014065b23d804ecf71a8a4691d076ca87c2e6fb8fe81ee20a4d8e884c24' const block = await Block.fromEthersProvider(provider, blockHash, { common }) t.equal( - '0x' + block.hash().toString('hex'), + bytesToPrefixedHexString(block.hash()), blockHash, 'assembled a block from blockdata from a provider' ) diff --git a/packages/block/test/header.spec.ts b/packages/block/test/header.spec.ts index b966b2a082..c15e653f69 100644 --- a/packages/block/test/header.spec.ts +++ b/packages/block/test/header.spec.ts @@ -1,6 +1,16 @@ import { Chain, Common, Hardfork } from '@ethereumjs/common' import { RLP } from '@ethereumjs/rlp' -import { Address, KECCAK256_RLP, KECCAK256_RLP_ARRAY, toBuffer, zeros } from '@ethereumjs/util' +import { + Address, + KECCAK256_RLP, + KECCAK256_RLP_ARRAY, + bytesToHex, + concatBytes, + equalsBytes, + hexStringToBytes, + toBytes, + zeros, +} from '@ethereumjs/util' import * as tape from 'tape' import { Block } from '../src' @@ -14,21 +24,21 @@ const blocksMainnet = require('./testdata/blocks_mainnet.json') tape('[Block]: Header functions', function (t) { t.test('should create with default constructor', function (st) { function compareDefaultHeader(st: tape.Test, header: BlockHeader) { - st.ok(header.parentHash.equals(zeros(32))) - st.ok(header.uncleHash.equals(KECCAK256_RLP_ARRAY)) + st.ok(equalsBytes(header.parentHash, zeros(32))) + st.ok(equalsBytes(header.uncleHash, KECCAK256_RLP_ARRAY)) st.ok(header.coinbase.equals(Address.zero())) - st.ok(header.stateRoot.equals(zeros(32))) - st.ok(header.transactionsTrie.equals(KECCAK256_RLP)) - st.ok(header.receiptTrie.equals(KECCAK256_RLP)) - st.ok(header.logsBloom.equals(zeros(256))) + st.ok(equalsBytes(header.stateRoot, zeros(32))) + st.ok(equalsBytes(header.transactionsTrie, KECCAK256_RLP)) + st.ok(equalsBytes(header.receiptTrie, KECCAK256_RLP)) + st.ok(equalsBytes(header.logsBloom, zeros(256))) st.equal(header.difficulty, BigInt(0)) st.equal(header.number, BigInt(0)) st.equal(header.gasLimit, BigInt('0xffffffffffffff')) st.equal(header.gasUsed, BigInt(0)) st.equal(header.timestamp, BigInt(0)) - st.ok(header.extraData.equals(Buffer.from([]))) - st.ok(header.mixHash.equals(zeros(32))) - st.ok(header.nonce.equals(zeros(8))) + st.ok(equalsBytes(header.extraData, new Uint8Array(0))) + st.ok(equalsBytes(header.mixHash, zeros(32))) + st.ok(equalsBytes(header.nonce, zeros(8))) } const header = BlockHeader.fromHeaderData() @@ -43,7 +53,7 @@ tape('[Block]: Header functions', function (t) { t.test('Initialization -> fromHeaderData()', function (st) { const common = new Common({ chain: Chain.Ropsten, hardfork: Hardfork.Chainstart }) let header = BlockHeader.fromHeaderData(undefined, { common }) - st.ok(header.hash().toString('hex'), 'genesis block should initialize') + st.ok(bytesToHex(header.hash()), 'genesis block should initialize') st.equal(header._common.hardfork(), 'chainstart', 'should initialize with correct HF provided') common.setHardfork(Hardfork.Byzantium) @@ -54,7 +64,7 @@ tape('[Block]: Header functions', function (t) { ) header = BlockHeader.fromHeaderData({}, { common }) - st.ok(header.hash().toString('hex'), 'default block should initialize') + st.ok(bytesToHex(header.hash()), 'default block should initialize') // test default freeze values // also test if the options are carried over to the constructor @@ -94,14 +104,13 @@ tape('[Block]: Header functions', function (t) { ) header = BlockHeader.fromRLPSerializedHeader( - Buffer.from( - 'f90214a00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0d7f8974fb5ac78d9ac099b9ad5018bedc2ce0a72dad1827a1709da30580f0544a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000850400000000808213888080a011bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82faa00000000000000000000000000000000000000000000000000000000000000000880000000000000042', - 'hex' + hexStringToBytes( + 'f90214a00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0d7f8974fb5ac78d9ac099b9ad5018bedc2ce0a72dad1827a1709da30580f0544a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000850400000000808213888080a011bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82faa00000000000000000000000000000000000000000000000000000000000000000880000000000000042' ), { common, hardforkByBlockNumber: false } ) st.equal( - header.hash().toString('hex'), + bytesToHex(header.hash()), 'f0f936910ebf101b7b168bbe08e3f166ce1e75e16f513dd5a97af02fbe7de7c0', 'genesis block should produce incorrect hash since default hardfork is london' ) @@ -110,7 +119,7 @@ tape('[Block]: Header functions', function (t) { t.test('Initialization -> fromRLPSerializedHeader() -> error cases', function (st) { try { - BlockHeader.fromRLPSerializedHeader(Buffer.from(RLP.encode('a'))) + BlockHeader.fromRLPSerializedHeader(RLP.encode('a')) } catch (e: any) { const expectedError = 'Invalid serialized header input. Must be array' st.ok(e.message.includes(expectedError), 'should throw with header as rlp encoded string') @@ -120,7 +129,7 @@ tape('[Block]: Header functions', function (t) { t.test('Initialization -> fromValuesArray()', function (st) { const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.London }) - const zero = Buffer.alloc(0) + const zero = new Uint8Array(0) const headerArray = [] for (let item = 0; item < 15; item++) { headerArray.push(zero) @@ -144,7 +153,7 @@ tape('[Block]: Header functions', function (t) { }) t.test('Initialization -> fromValuesArray() -> error cases', function (st) { - const headerArray = Array(19).fill(Buffer.alloc(0)) + const headerArray = Array(19).fill(new Uint8Array(0)) // mock header data (if set to zeros(0) header throws) headerArray[0] = zeros(32) //parentHash @@ -173,8 +182,8 @@ tape('[Block]: Header functions', function (t) { t.test('Initialization -> Clique Blocks', function (st) { const common = new Common({ chain: Chain.Rinkeby, hardfork: Hardfork.Chainstart }) - const header = BlockHeader.fromHeaderData({ extraData: Buffer.alloc(97) }, { common }) - st.ok(header.hash().toString('hex'), 'default block should initialize') + const header = BlockHeader.fromHeaderData({ extraData: new Uint8Array(97) }, { common }) + st.ok(bytesToHex(header.hash()), 'default block should initialize') st.end() }) @@ -193,7 +202,7 @@ tape('[Block]: Header functions', function (t) { // valid extraData: at limit let testCase = 'pow block should validate with 32 bytes of extraData' - let extraData = Buffer.alloc(32) + let extraData = new Uint8Array(32) try { BlockHeader.fromHeaderData({ ...data, extraData }, opts) @@ -204,7 +213,7 @@ tape('[Block]: Header functions', function (t) { // valid extraData: fewer than limit testCase = 'pow block should validate with 12 bytes of extraData' - extraData = Buffer.alloc(12) + extraData = new Uint8Array(12) try { BlockHeader.fromHeaderData({ ...data, extraData }, opts) @@ -215,7 +224,7 @@ tape('[Block]: Header functions', function (t) { // extraData beyond limit testCase = 'pow block should throw with excess amount of extraData' - extraData = Buffer.alloc(42) + extraData = new Uint8Array(42) try { BlockHeader.fromHeaderData({ ...data, extraData }, opts) @@ -226,7 +235,7 @@ tape('[Block]: Header functions', function (t) { // PoA common = new Common({ chain: Chain.Rinkeby, hardfork: Hardfork.Chainstart }) - genesis = Block.fromBlockData({ header: { extraData: Buffer.alloc(97) } }, { common }) + genesis = Block.fromBlockData({ header: { extraData: new Uint8Array(97) } }, { common }) parentHash = genesis.hash() gasLimit = genesis.header.gasLimit @@ -236,7 +245,7 @@ tape('[Block]: Header functions', function (t) { // valid extraData (32 byte vanity + 65 byte seal) testCase = 'clique block should validate with valid number of bytes in extraData: 32 byte vanity + 65 byte seal' - extraData = Buffer.concat([Buffer.alloc(32), Buffer.alloc(65)]) + extraData = concatBytes(new Uint8Array(32), new Uint8Array(65)) try { BlockHeader.fromHeaderData({ ...data, extraData }, opts) t.pass(testCase) @@ -246,7 +255,7 @@ tape('[Block]: Header functions', function (t) { // invalid extraData length testCase = 'clique block should throw on invalid extraData length' - extraData = Buffer.alloc(32) + extraData = new Uint8Array(32) try { BlockHeader.fromHeaderData({ ...data, extraData }, opts) t.fail(testCase) @@ -261,12 +270,12 @@ tape('[Block]: Header functions', function (t) { // signer list indivisible by 20 testCase = 'clique blocks should throw on invalid extraData length: indivisible by 20' - extraData = Buffer.concat([ - Buffer.alloc(32), - Buffer.alloc(65), - Buffer.alloc(20), - Buffer.alloc(21), - ]) + extraData = concatBytes( + new Uint8Array(32), + new Uint8Array(65), + new Uint8Array(20), + new Uint8Array(21) + ) const epoch = BigInt((common.consensusConfig() as CliqueConfig).epoch) try { BlockHeader.fromHeaderData({ ...data, number: epoch, extraData }, opts) @@ -285,7 +294,7 @@ tape('[Block]: Header functions', function (t) { t.test('should skip consensusFormatValidation if flag is set to false', (st) => { const common = new Common({ chain: Chain.Goerli, hardfork: Hardfork.Chainstart }) - const extraData = Buffer.concat([Buffer.alloc(1)]) + const extraData = concatBytes(new Uint8Array(1)) try { BlockHeader.fromHeaderData({ extraData }, { common, skipConsensusFormatValidation: true }) @@ -300,7 +309,7 @@ tape('[Block]: Header functions', function (t) { }) t.test('_genericFormatValidation checks', (st) => { - const badHash = Buffer.alloc(31) + const badHash = new Uint8Array(31) st.throws( () => BlockHeader.fromHeaderData({ parentHash: badHash }), @@ -319,7 +328,7 @@ tape('[Block]: Header functions', function (t) { ) st.throws( - () => BlockHeader.fromHeaderData({ nonce: Buffer.alloc(5) }), + () => BlockHeader.fromHeaderData({ nonce: new Uint8Array(5) }), (err: any) => err.message.includes('nonce must be 8 bytes'), 'contains nonce length error message' ) @@ -333,14 +342,14 @@ tape('[Block]: Header functions', function (t) { const common = new Common({ chain: Chain.Goerli, hardfork: Hardfork.Istanbul }) const blockchain = new Mockchain() - const genesisRlp = toBuffer(testDataPreLondon.genesisRLP) + const genesisRlp = toBytes(testDataPreLondon.genesisRLP) const block = Block.fromRLPSerializedBlock(genesisRlp, { common }) await blockchain.putBlock(block) headerData.number = 1 headerData.timestamp = BigInt(1422494850) - headerData.extraData = Buffer.alloc(97) - headerData.mixHash = Buffer.alloc(32) + headerData.extraData = new Uint8Array(97) + headerData.mixHash = new Uint8Array(32) headerData.difficulty = BigInt(2) let testCase = 'should throw on lower than period timestamp diffs' @@ -380,7 +389,7 @@ tape('[Block]: Header functions', function (t) { headerData.coinbase = Address.zero() testCase = 'should throw on non-zero mixHash' - headerData.mixHash = Buffer.alloc(32).fill(1) + headerData.mixHash = new Uint8Array(32).fill(1) header = BlockHeader.fromHeaderData(headerData, { common }) try { await header.validate(blockchain) @@ -392,7 +401,7 @@ tape('[Block]: Header functions', function (t) { st.fail('should throw with appropriate error') } } - headerData.mixHash = Buffer.alloc(32) + headerData.mixHash = new Uint8Array(32) testCase = 'should throw on invalid clique difficulty' headerData.difficulty = BigInt(3) @@ -411,9 +420,8 @@ tape('[Block]: Header functions', function (t) { testCase = 'validateCliqueDifficulty() should return true with NOTURN difficulty and one signer' headerData.difficulty = BigInt(2) const poaBlockchain = new PoaMockchain() - const cliqueSigner = Buffer.from( - '64bf9cc30328b0e42387b3c82c614e6386259136235e20c1357bd11cdee86993', - 'hex' + const cliqueSigner = hexToBytes( + '64bf9cc30328b0e42387b3c82c614e6386259136235e20c1357bd11cdee86993' ) const poaBlock = Block.fromRLPSerializedBlock(genesisRlp, { common, cliqueSigner }) await poaBlockchain.putBlock(poaBlock) @@ -445,9 +453,9 @@ tape('[Block]: Header functions', function (t) { const bcBlockGasLimitTestData = testData.BlockGasLimit2p63m1 for (const key of Object.keys(bcBlockGasLimitTestData)) { - const genesisRlp = toBuffer(bcBlockGasLimitTestData[key].genesisRLP) + const genesisRlp = toBytes(bcBlockGasLimitTestData[key].genesisRLP) const parentBlock = Block.fromRLPSerializedBlock(genesisRlp, { common }) - const blockRlp = toBuffer(bcBlockGasLimitTestData[key].blocks[0].rlp) + const blockRlp = toBytes(bcBlockGasLimitTestData[key].blocks[0].rlp) const block = Block.fromRLPSerializedBlock(blockRlp, { common }) st.doesNotThrow(() => block.validateGasLimit(parentBlock)) } @@ -468,7 +476,7 @@ tape('[Block]: Header functions', function (t) { let common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Chainstart }) let header = BlockHeader.fromHeaderData(blocksMainnet[0]['header'], { common }) st.equal( - header.hash().toString('hex'), + bytesToHex(header.hash()), '88e96d4537bea4d9c05d12549907b32561d3bf31f45aae734cdc119f13406cb6', 'correct PoW hash (mainnet block 1)' ) @@ -476,7 +484,7 @@ tape('[Block]: Header functions', function (t) { common = new Common({ chain: Chain.Goerli, hardfork: Hardfork.Chainstart }) header = BlockHeader.fromHeaderData(blocksGoerli[0]['header'], { common }) st.equal( - header.hash().toString('hex'), + bytesToHex(header.hash()), '8f5bab218b6bb34476f51ca588e9f4553a3a7ce5e13a66c660a5283e97e9a85a', 'correct PoA clique hash (goerli block 1)' ) diff --git a/packages/block/test/mergeBlock.spec.ts b/packages/block/test/mergeBlock.spec.ts index e9bd5620a9..3761501ef6 100644 --- a/packages/block/test/mergeBlock.spec.ts +++ b/packages/block/test/mergeBlock.spec.ts @@ -1,5 +1,12 @@ import { Chain, Common, Hardfork } from '@ethereumjs/common' -import { Address, KECCAK256_RLP, KECCAK256_RLP_ARRAY, zeros } from '@ethereumjs/util' +import { + Address, + KECCAK256_RLP, + KECCAK256_RLP_ARRAY, + equalsBytes, + hexStringToBytes, + zeros, +} from '@ethereumjs/util' import * as tape from 'tape' import { Block } from '../src/block' @@ -11,13 +18,13 @@ const common = new Common({ }) function validateMergeHeader(st: tape.Test, header: BlockHeader) { - st.ok(header.parentHash.equals(zeros(32)), 'parentHash') - st.ok(header.uncleHash.equals(KECCAK256_RLP_ARRAY), 'uncleHash') + st.ok(equalsBytes(header.parentHash, zeros(32)), 'parentHash') + st.ok(equalsBytes(header.uncleHash, KECCAK256_RLP_ARRAY), 'uncleHash') st.ok(header.coinbase.equals(Address.zero()), 'coinbase') - st.ok(header.stateRoot.equals(zeros(32)), 'stateRoot') - st.ok(header.transactionsTrie.equals(KECCAK256_RLP), 'transactionsTrie') - st.ok(header.receiptTrie.equals(KECCAK256_RLP), 'receiptTrie') - st.ok(header.logsBloom.equals(zeros(256)), 'logsBloom') + st.ok(equalsBytes(header.stateRoot, zeros(32)), 'stateRoot') + st.ok(equalsBytes(header.transactionsTrie, KECCAK256_RLP), 'transactionsTrie') + st.ok(equalsBytes(header.receiptTrie, KECCAK256_RLP), 'receiptTrie') + st.ok(equalsBytes(header.logsBloom, zeros(256)), 'logsBloom') st.equal(header.difficulty, BigInt(0), 'difficulty') st.equal(header.number, BigInt(0), 'number') st.equal(header.gasLimit, BigInt('0xffffffffffffff'), 'gasLimit') @@ -25,7 +32,7 @@ function validateMergeHeader(st: tape.Test, header: BlockHeader) { st.equal(header.timestamp, BigInt(0), 'timestamp') st.ok(header.extraData.length <= 32, 'extraData') st.equal(header.mixHash.length, 32, 'mixHash') - st.ok(header.nonce.equals(zeros(8)), 'nonce') + st.ok(equalsBytes(header.nonce, zeros(8)), 'nonce') } tape('[Header]: Casper PoS / The Merge Functionality', function (t) { @@ -43,7 +50,7 @@ tape('[Header]: Casper PoS / The Merge Functionality', function (t) { // Building a header with random values for constants try { const headerData = { - uncleHash: Buffer.from('123abc', 'hex'), + uncleHash: hexStringToBytes('123abc'), } BlockHeader.fromHeaderData(headerData, { common }) st.fail('should throw') @@ -64,7 +71,7 @@ tape('[Header]: Casper PoS / The Merge Functionality', function (t) { try { const headerData = { - extraData: Buffer.alloc(33).fill(1), + extraData: new Uint8Array(33).fill(1), number: 1n, } BlockHeader.fromHeaderData(headerData, { common }) @@ -75,7 +82,7 @@ tape('[Header]: Casper PoS / The Merge Functionality', function (t) { try { const headerData = { - mixHash: Buffer.alloc(30).fill(1), + mixHash: new Uint8Array(30).fill(1), } BlockHeader.fromHeaderData(headerData, { common }) st.fail('should throw') @@ -85,7 +92,7 @@ tape('[Header]: Casper PoS / The Merge Functionality', function (t) { try { const headerData = { - nonce: Buffer.alloc(8).fill(1), + nonce: new Uint8Array(8).fill(1), number: 1n, } BlockHeader.fromHeaderData(headerData, { common }) @@ -110,9 +117,9 @@ tape('[Header]: Casper PoS / The Merge Functionality', function (t) { }) t.test('EIP-4399: prevRando should return mixHash value', function (st) { - const mixHash = Buffer.alloc(32, 3) + const mixHash = new Uint8Array(32).fill(3) let block = Block.fromBlockData({ header: { mixHash } }, { common }) - st.ok(block.header.prevRandao.equals(mixHash), 'prevRandao should return mixHash value') + st.ok(equalsBytes(block.header.prevRandao, mixHash), 'prevRandao should return mixHash value') const commonLondon = common.copy() commonLondon.setHardfork(Hardfork.London) diff --git a/packages/block/test/util.ts b/packages/block/test/util.ts index 7f4f0c9b91..bf6c6f6aef 100644 --- a/packages/block/test/util.ts +++ b/packages/block/test/util.ts @@ -1,6 +1,6 @@ import { Chain, Common, Hardfork } from '@ethereumjs/common' import { RLP } from '@ethereumjs/rlp' -import { bufArrToArr } from '@ethereumjs/util' +import { utf8ToBytes } from '@ethereumjs/util' import { keccak256 } from 'ethereum-cryptography/keccak' import { Block } from '../src' @@ -29,7 +29,7 @@ function createBlock( const number = parentBlock.header.number + BigInt(1) const timestamp = parentBlock.header.timestamp + BigInt(1) - const uncleHash = keccak256(RLP.encode(bufArrToArr(uncles.map((uh) => uh.raw())))) + const uncleHash = keccak256(RLP.encode(uncles.map((uh) => uh.raw()))) const londonHfBlock = common.hardforkBlock(Hardfork.London) const baseFeePerGas = @@ -44,7 +44,7 @@ function createBlock( parentHash: parentBlock.hash(), timestamp, gasLimit: parentBlock.header.gasLimit, - extraData: Buffer.from(extraData), + extraData: utf8ToBytes(extraData), uncleHash, baseFeePerGas, }, diff --git a/packages/blockchain/src/blockchain.ts b/packages/blockchain/src/blockchain.ts index 7704a7bafd..c3c366f59f 100644 --- a/packages/blockchain/src/blockchain.ts +++ b/packages/blockchain/src/blockchain.ts @@ -1,6 +1,7 @@ import { Block, BlockHeader } from '@ethereumjs/block' import { Chain, Common, ConsensusAlgorithm, ConsensusType, Hardfork } from '@ethereumjs/common' -import { KECCAK256_RLP, Lock } from '@ethereumjs/util' +import { KECCAK256_RLP, Lock, concatBytesNoTypeCheck } from '@ethereumjs/util' +import { bytesToHex, equalsBytes, hexToBytes } from 'ethereum-cryptography/utils' import { MemoryLevel } from 'memory-level' import { CasperConsensus, CliqueConsensus, EthashConsensus } from './consensus' @@ -23,7 +24,7 @@ import type { AbstractLevel } from 'abstract-level' */ export class Blockchain implements BlockchainInterface { consensus: Consensus - db: AbstractLevel + db: AbstractLevel dbManager: DBManager private _genesisBlock?: Block /** The genesis block of this blockchain */ @@ -36,16 +37,16 @@ export class Blockchain implements BlockchainInterface { * the hash with the highest total difficulty. */ /** The hash of the current head block */ - private _headBlockHash?: Buffer + private _headBlockHash?: Uint8Array /** The hash of the current head header */ - private _headHeaderHash?: Buffer + private _headHeaderHash?: Uint8Array /** * A Map which stores the head of each key (for instance the "vm" key) which is * updated along a {@link Blockchain.iterator} method run and can be used to (re)run * non-verified blocks (for instance in the VM). */ - private _heads: { [key: string]: Buffer } + private _heads: { [key: string]: Uint8Array } protected _isInitialized = false private _lock: Lock @@ -204,10 +205,7 @@ export class Blockchain implements BlockchainInterface { let stateRoot if (this._common.chainId() === BigInt(1) && this._customGenesisState === undefined) { // For mainnet use the known genesis stateRoot to quicken setup - stateRoot = Buffer.from( - 'd7f8974fb5ac78d9ac099b9ad5018bedc2ce0a72dad1827a1709da30580f0544', - 'hex' - ) + stateRoot = hexToBytes('d7f8974fb5ac78d9ac099b9ad5018bedc2ce0a72dad1827a1709da30580f0544') } else { stateRoot = await genesisStateRoot(this.genesisState()) } @@ -216,7 +214,7 @@ export class Blockchain implements BlockchainInterface { // If the DB has a genesis block, then verify that the genesis block in the // DB is indeed the Genesis block generated or assigned. - if (dbGenesisBlock && !genesisBlock.hash().equals(dbGenesisBlock.hash())) { + if (dbGenesisBlock && !equalsBytes(genesisBlock.hash(), dbGenesisBlock.hash())) { throw new Error( 'The genesis block in the DB has a different hash than the provided genesis block.' ) @@ -691,11 +689,11 @@ export class Blockchain implements BlockchainInterface { canonicalBlockMap.push(parentBlock) // mark block hash as part of the canonical chain - canonicalChainHashes[parentBlock.hash().toString('hex')] = true + canonicalChainHashes[bytesToHex(parentBlock.hash())] = true // for each of the uncles, mark the uncle as included parentBlock.uncleHeaders.map((uh) => { - includedUncles[uh.hash().toString('hex')] = true + includedUncles[bytesToHex(uh.hash())] = true }) parentHash = parentBlock.header.parentHash @@ -707,8 +705,8 @@ export class Blockchain implements BlockchainInterface { // Uncle Header has a parentHash which points to the canonical chain. uncleHeaders.map((uh) => { - const uncleHash = uh.hash().toString('hex') - const parentHash = uh.parentHash.toString('hex') + const uncleHash = bytesToHex(uh.hash()) + const parentHash = bytesToHex(uh.parentHash) if (!canonicalChainHashes[parentHash]) { throw new Error( @@ -734,7 +732,7 @@ export class Blockchain implements BlockchainInterface { * this will be immediately looked up, otherwise it will wait until we have * unlocked the DB */ - async getBlock(blockId: Buffer | number | bigint): Promise { + async getBlock(blockId: Uint8Array | number | bigint): Promise { // cannot wait for a lock here: it is used both in `validate` of `Block` // (calls `getBlock` to get `parentHash`) it is also called from `runBlock` // in the `VM` if we encounter a `BLOCKHASH` opcode: then a bigint is used we @@ -745,7 +743,7 @@ export class Blockchain implements BlockchainInterface { } catch (error: any) { if (error.code === 'LEVEL_NOT_FOUND') { if (typeof blockId === 'object') { - error.message = `Block with hash ${blockId.toString('hex')} not found in DB (NotFound)` + error.message = `Block with hash ${bytesToHex(blockId)} not found in DB (NotFound)` } else { error.message = `Block number ${blockId} not found in DB (NotFound)` } @@ -757,7 +755,7 @@ export class Blockchain implements BlockchainInterface { /** * Gets total difficulty for a block specified by hash and number */ - public async getTotalDifficulty(hash: Buffer, number?: bigint): Promise { + public async getTotalDifficulty(hash: Uint8Array, number?: bigint): Promise { if (number === undefined) { number = await this.dbManager.hashToNumber(hash) } @@ -783,7 +781,7 @@ export class Blockchain implements BlockchainInterface { * @param reverse - Fetch blocks in reverse */ async getBlocks( - blockId: Buffer | bigint | number, + blockId: Uint8Array | bigint | number, maxBlocks: number, skip: number, reverse: boolean @@ -792,7 +790,7 @@ export class Blockchain implements BlockchainInterface { const blocks: Block[] = [] let i = -1 - const nextBlock = async (blockId: Buffer | bigint | number): Promise => { + const nextBlock = async (blockId: Uint8Array | bigint | number): Promise => { let block try { block = await this.getBlock(blockId) @@ -824,8 +822,8 @@ export class Blockchain implements BlockchainInterface { * Therefore, the array needs to be ordered upon number. * @param hashes - Ordered array of hashes (ordered on `number`). */ - async selectNeededHashes(hashes: Array): Promise { - return this.runWithLock(async () => { + async selectNeededHashes(hashes: Array): Promise { + return this.runWithLock(async () => { let max: number let mid: number let min: number @@ -864,7 +862,7 @@ export class Blockchain implements BlockchainInterface { * we can be sure it is correct). * @param blockHash - The hash of the block to be deleted */ - async delBlock(blockHash: Buffer) { + async delBlock(blockHash: Uint8Array) { // Q: is it safe to make this not wait for a lock? this is called from // `BlockchainTestsRunner` in case `runBlock` throws (i.e. the block is invalid). // But is this the way to go? If we know this is called from the @@ -876,7 +874,7 @@ export class Blockchain implements BlockchainInterface { /** * @hidden */ - private async _delBlock(blockHash: Buffer) { + private async _delBlock(blockHash: Uint8Array) { const dbOps: DBOp[] = [] // get header @@ -888,7 +886,7 @@ export class Blockchain implements BlockchainInterface { // check if block is in the canonical chain const canonicalHash = await this.safeNumberToHash(blockNumber) - const inCanonical = canonicalHash !== false && canonicalHash.equals(blockHash) + const inCanonical = canonicalHash !== false && equalsBytes(canonicalHash, blockHash) // delete the block, and if block is in the canonical chain, delete all // children as well @@ -918,9 +916,9 @@ export class Blockchain implements BlockchainInterface { * @hidden */ private async _delChild( - blockHash: Buffer, + blockHash: Uint8Array, blockNumber: bigint, - headHash: Buffer | null, + headHash: Uint8Array | null, ops: DBOp[] ) { // delete header, body, hash to number mapping and td @@ -933,11 +931,14 @@ export class Blockchain implements BlockchainInterface { return } - if (this._headHeaderHash?.equals(blockHash) === true) { + if ( + this._headHeaderHash !== undefined && + equalsBytes(this._headHeaderHash, blockHash) === true + ) { this._headHeaderHash = headHash } - if (this._headBlockHash?.equals(blockHash) === true) { + if (this._headBlockHash !== undefined && equalsBytes(this._headBlockHash, blockHash)) { this._headBlockHash = headHash } @@ -983,7 +984,9 @@ export class Blockchain implements BlockchainInterface { while (maxBlocks !== blocksRanCounter) { try { let nextBlock = await this.getBlock(nextBlockNumber) - const reorg = lastBlock ? !lastBlock.hash().equals(nextBlock.header.parentHash) : false + const reorg = lastBlock + ? !equalsBytes(lastBlock.hash(), nextBlock.header.parentHash) + : false if (reorg) { // If reorg has happened, the _heads must have been updated so lets reload the counters headHash = this._heads[name] ?? this.genesisBlock.hash() @@ -1025,7 +1028,7 @@ export class Blockchain implements BlockchainInterface { * @param tag - The tag to save the headHash to * @param headHash - The head hash to save */ - async setIteratorHead(tag: string, headHash: Buffer) { + async setIteratorHead(tag: string, headHash: Uint8Array) { await this.runWithLock(async () => { this._heads[tag] = headHash await this._saveHeads() @@ -1055,13 +1058,13 @@ export class Blockchain implements BlockchainInterface { if (header.number !== newHeader.number) { throw new Error('Failed to find ancient header') } - while (!header.hash().equals(newHeader.hash()) && header.number > BigInt(0)) { + while (!equalsBytes(header.hash(), newHeader.hash()) && header.number > BigInt(0)) { header = await this.getCanonicalHeader(header.number - BigInt(1)) ancestorHeaders.add(header) newHeader = await this._getHeader(newHeader.parentHash, newHeader.number - BigInt(1)) ancestorHeaders.add(newHeader) } - if (!header.hash().equals(newHeader.hash())) { + if (!equalsBytes(header.hash(), newHeader.hash())) { throw new Error('Failed to find ancient header') } return { @@ -1085,10 +1088,10 @@ export class Blockchain implements BlockchainInterface { */ private async _deleteCanonicalChainReferences( blockNumber: bigint, - headHash: Buffer, + headHash: Uint8Array, ops: DBOp[] ) { - let hash: Buffer | false + let hash: Uint8Array | false hash = await this.safeNumberToHash(blockNumber) while (hash !== false) { @@ -1099,18 +1102,18 @@ export class Blockchain implements BlockchainInterface { // executed block) blocks to verify the chain up to the current, actual, // head. for (const name of Object.keys(this._heads)) { - if (this._heads[name].equals(hash)) { + if (equalsBytes(this._heads[name], hash)) { this._heads[name] = headHash } } - // reset stale headBlock to current canonical - if (this._headBlockHash?.equals(hash) === true) { - this._headBlockHash = headHash + // reset stale headHeader to current canonical + if (this._headHeaderHash !== undefined && equalsBytes(this._headHeaderHash, hash) === true) { + this._headHeaderHash = headHash } // reset stale headBlock to current canonical - if (this._headHeaderHash?.equals(hash) === true) { - this._headHeaderHash = headHash + if (this._headBlockHash !== undefined && equalsBytes(this._headBlockHash, hash) === true) { + this._headBlockHash = headHash } blockNumber++ @@ -1136,18 +1139,18 @@ export class Blockchain implements BlockchainInterface { */ private async _rebuildCanonical(header: BlockHeader, ops: DBOp[]) { let currentNumber = header.number - let currentCanonicalHash: Buffer = header.hash() + let currentCanonicalHash: Uint8Array = header.hash() // track the staleHash: this is the hash currently in the DB which matches // the block number of the provided header. - let staleHash: Buffer | false = false + let staleHash: Uint8Array | false = false let staleHeads: string[] = [] let staleHeadBlock = false const loopCondition = async () => { staleHash = await this.safeNumberToHash(currentNumber) currentCanonicalHash = header.hash() - return staleHash === false || !currentCanonicalHash.equals(staleHash) + return staleHash === false || !equalsBytes(currentCanonicalHash, staleHash) } while (await loopCondition()) { @@ -1166,12 +1169,16 @@ export class Blockchain implements BlockchainInterface { // mark each key `_heads` which is currently set to the hash in the DB as // stale to overwrite later in `_deleteCanonicalChainReferences`. for (const name of Object.keys(this._heads)) { - if (staleHash && this._heads[name].equals(staleHash)) { + if (staleHash && equalsBytes(this._heads[name], staleHash)) { staleHeads.push(name) } } // flag stale headBlock for reset - if (staleHash && this._headBlockHash?.equals(staleHash) === true) { + if ( + staleHash && + this._headBlockHash !== undefined && + equalsBytes(this._headBlockHash, staleHash) === true + ) { staleHeadBlock = true } @@ -1226,7 +1233,7 @@ export class Blockchain implements BlockchainInterface { * * @hidden */ - private async _getHeader(hash: Buffer, number?: bigint) { + private async _getHeader(hash: Uint8Array, number?: bigint) { if (number === undefined) { number = await this.dbManager.hashToNumber(hash) } @@ -1276,12 +1283,12 @@ export class Blockchain implements BlockchainInterface { } /** - * This method either returns a Buffer if there exists one in the DB or if it + * This method either returns a Uint8Array if there exists one in the DB or if it * does not exist (DB throws a `NotFoundError`) then return false If DB throws * any other error, this function throws. * @param number */ - async safeNumberToHash(number: bigint): Promise { + async safeNumberToHash(number: bigint): Promise { try { const hash = await this.dbManager.numberToHash(number) return hash @@ -1305,7 +1312,7 @@ export class Blockchain implements BlockchainInterface { * Creates a genesis {@link Block} for the blockchain with params from {@link Common.genesis} * @param stateRoot The genesis stateRoot */ - createGenesisBlock(stateRoot: Buffer): Block { + createGenesisBlock(stateRoot: Uint8Array): Block { const common = this._common.copy() common.setHardforkByBlockNumber( 0, @@ -1326,7 +1333,7 @@ export class Blockchain implements BlockchainInterface { header.extraData = common.genesis().extraData } else { // Add required extraData (32 bytes vanity + 65 bytes filled with zeroes - header.extraData = Buffer.concat([Buffer.alloc(32), Buffer.alloc(65).fill(0)]) + header.extraData = concatBytesNoTypeCheck(new Uint8Array(32), new Uint8Array(65)) } } return Block.fromBlockData( diff --git a/packages/blockchain/src/consensus/clique.ts b/packages/blockchain/src/consensus/clique.ts index e7ec9b503e..b28760f788 100644 --- a/packages/blockchain/src/consensus/clique.ts +++ b/packages/blockchain/src/consensus/clique.ts @@ -1,7 +1,8 @@ import { ConsensusAlgorithm } from '@ethereumjs/common' import { RLP } from '@ethereumjs/rlp' -import { Address, arrToBufArr, bigIntToBuffer, bufArrToArr, bufferToBigInt } from '@ethereumjs/util' +import { Address, TypeOutput, bigIntToBytes, bytesToBigInt, toType } from '@ethereumjs/util' import { debug as createDebugLogger } from 'debug' +import { equalsBytes, hexToBytes } from 'ethereum-cryptography/utils' import type { Blockchain } from '..' import type { Consensus, ConsensusOptions } from './interface' @@ -11,9 +12,9 @@ import type { CliqueConfig } from '@ethereumjs/common' const debug = createDebugLogger('blockchain:clique') // Magic nonce number to vote on adding a new signer -export const CLIQUE_NONCE_AUTH = Buffer.from('ffffffffffffffff', 'hex') +export const CLIQUE_NONCE_AUTH = hexToBytes('ffffffffffffffff') // Magic nonce number to vote on removing a signer. -export const CLIQUE_NONCE_DROP = Buffer.alloc(8) +export const CLIQUE_NONCE_DROP = new Uint8Array(8) const CLIQUE_SIGNERS_KEY = 'CliqueSigners' const CLIQUE_VOTES_KEY = 'CliqueVotes' @@ -25,8 +26,8 @@ export const CLIQUE_DIFF_INTURN = BigInt(2) export const CLIQUE_DIFF_NOTURN = BigInt(1) const DB_OPTS = { - keyEncoding: 'buffer', - valueEncoding: 'buffer', + keyEncoding: 'view', + valueEncoding: 'view', } // Clique Signer State @@ -36,7 +37,7 @@ type CliqueLatestSignerStates = CliqueSignerState[] // Clique Vote type CliqueVote = [ blockNumber: bigint, - vote: [signer: Address, beneficiary: Address, cliqueNonce: Buffer] + vote: [signer: Address, beneficiary: Address, cliqueNonce: Uint8Array] ] type CliqueLatestVotes = CliqueVote[] @@ -234,14 +235,10 @@ export class CliqueConsensus implements Consensus { // save to db const formatted = this._cliqueLatestSignerStates.map((state) => [ - bigIntToBuffer(state[0]), - state[1].map((a) => a.toBuffer()), + bigIntToBytes(state[0]), + state[1].map((a) => a.toBytes()), ]) - await this.blockchain!.db.put( - CLIQUE_SIGNERS_KEY, - Buffer.from(RLP.encode(bufArrToArr(formatted))), - DB_OPTS - ) + await this.blockchain!.db.put(CLIQUE_SIGNERS_KEY, RLP.encode(formatted), DB_OPTS) // Output active signers for debugging purposes let i = 0 for (const signer of this.cliqueActiveSigners()) { @@ -281,7 +278,7 @@ export class CliqueConsensus implements Consensus { vote[0] >= BigInt(lastEpochBlockNumber) && !vote[1][0].equals(signer) && vote[1][1].equals(beneficiary) && - vote[1][2].equals(CLIQUE_NONCE_AUTH) + equalsBytes(vote[1][2], CLIQUE_NONCE_AUTH) ) }) const beneficiaryVotesAUTH: Address[] = [] @@ -294,7 +291,7 @@ export class CliqueConsensus implements Consensus { } } let numBeneficiaryVotesAUTH = beneficiaryVotesAUTH.length - if (round === 2 && nonce.equals(CLIQUE_NONCE_AUTH)) { + if (round === 2 && equalsBytes(nonce, CLIQUE_NONCE_AUTH)) { numBeneficiaryVotesAUTH += 1 } // Majority consensus @@ -303,8 +300,14 @@ export class CliqueConsensus implements Consensus { // Authorize new signer activeSigners.push(beneficiary) activeSigners.sort((a, b) => { - // Sort by buffer size - return a.toBuffer().compare(b.toBuffer()) + // Sort by array size + const result = + toType(a.toString(), TypeOutput.BigInt) < toType(b.toString(), TypeOutput.BigInt) + if (result) { + return -1 + } else { + return 1 + } }) // Discard votes for added signer this._cliqueLatestVotes = this._cliqueLatestVotes.filter( @@ -318,7 +321,7 @@ export class CliqueConsensus implements Consensus { vote[0] >= BigInt(lastEpochBlockNumber) && !vote[1][0].equals(signer) && vote[1][1].equals(beneficiary) && - vote[1][2].equals(CLIQUE_NONCE_DROP) + equalsBytes(vote[1][2], CLIQUE_NONCE_DROP) ) }) const beneficiaryVotesDROP: Address[] = [] @@ -332,7 +335,7 @@ export class CliqueConsensus implements Consensus { } let numBeneficiaryVotesDROP = beneficiaryVotesDROP.length - if (round === 2 && nonce.equals(CLIQUE_NONCE_DROP)) { + if (round === 2 && equalsBytes(nonce, CLIQUE_NONCE_DROP)) { numBeneficiaryVotesDROP += 1 } // Majority consensus @@ -352,7 +355,7 @@ export class CliqueConsensus implements Consensus { this._cliqueLatestVotes.push(latestVote) debug( `[Block ${header.number}] New clique vote: ${signer} -> ${beneficiary} ${ - nonce.equals(CLIQUE_NONCE_AUTH) ? 'AUTH' : 'DROP' + equalsBytes(nonce, CLIQUE_NONCE_AUTH) ? 'AUTH' : 'DROP' }` ) } @@ -388,14 +391,10 @@ export class CliqueConsensus implements Consensus { // save votes to db const formatted = this._cliqueLatestVotes.map((v) => [ - bigIntToBuffer(v[0]), - [v[1][0].toBuffer(), v[1][1].toBuffer(), v[1][2]], + bigIntToBytes(v[0]), + [v[1][0].toBytes(), v[1][1].toBytes(), v[1][2]], ]) - await this.blockchain!.db.put( - CLIQUE_VOTES_KEY, - Buffer.from(RLP.encode(bufArrToArr(formatted))), - DB_OPTS - ) + await this.blockchain!.db.put(CLIQUE_VOTES_KEY, RLP.encode(formatted), DB_OPTS) } /** @@ -496,14 +495,10 @@ export class CliqueConsensus implements Consensus { // save to db const formatted = this._cliqueLatestBlockSigners.map((b) => [ - bigIntToBuffer(b[0]), - b[1].toBuffer(), + bigIntToBytes(b[0]), + b[1].toBytes(), ]) - await this.blockchain!.db.put( - CLIQUE_BLOCK_SIGNERS_SNAPSHOT_KEY, - Buffer.from(RLP.encode(bufArrToArr(formatted))), - DB_OPTS - ) + await this.blockchain!.db.put(CLIQUE_BLOCK_SIGNERS_SNAPSHOT_KEY, RLP.encode(formatted), DB_OPTS) } /** @@ -512,14 +507,14 @@ export class CliqueConsensus implements Consensus { */ private async getCliqueLatestSignerStates(): Promise { try { - const signerStates = await this.blockchain!.db.get( + const signerStates = await this.blockchain!.db.get( CLIQUE_SIGNERS_KEY, DB_OPTS ) - const states = arrToBufArr(RLP.decode(Uint8Array.from(signerStates))) as [Buffer, Buffer[]] + const states = RLP.decode(signerStates) as [Uint8Array, Uint8Array[]] return states.map((state) => { - const blockNum = bufferToBigInt(state[0] as Buffer) - const addrs = (state[1]).map((buf: Buffer) => new Address(buf)) + const blockNum = bytesToBigInt(state[0] as Uint8Array) + const addrs = (state[1]).map((bytes: Uint8Array) => new Address(bytes)) return [blockNum, addrs] }) as CliqueLatestSignerStates } catch (error: any) { @@ -536,13 +531,13 @@ export class CliqueConsensus implements Consensus { */ private async getCliqueLatestVotes(): Promise { try { - const signerVotes = await this.blockchain!.db.get(CLIQUE_VOTES_KEY, DB_OPTS) - const votes = arrToBufArr(RLP.decode(Uint8Array.from(signerVotes))) as [ - Buffer, - [Buffer, Buffer, Buffer] - ] + const signerVotes = await this.blockchain!.db.get( + CLIQUE_VOTES_KEY, + DB_OPTS + ) + const votes = RLP.decode(signerVotes) as [Uint8Array, [Uint8Array, Uint8Array, Uint8Array]] return votes.map((vote) => { - const blockNum = bufferToBigInt(vote[0] as Buffer) + const blockNum = bytesToBigInt(vote[0] as Uint8Array) const signer = new Address((vote[1] as any)[0]) const beneficiary = new Address((vote[1] as any)[1]) const nonce = (vote[1] as any)[2] @@ -562,13 +557,13 @@ export class CliqueConsensus implements Consensus { */ private async getCliqueLatestBlockSigners(): Promise { try { - const blockSigners = await this.blockchain!.db.get( + const blockSigners = await this.blockchain!.db.get( CLIQUE_BLOCK_SIGNERS_SNAPSHOT_KEY, DB_OPTS ) - const signers = arrToBufArr(RLP.decode(Uint8Array.from(blockSigners))) as [Buffer, Buffer][] + const signers = RLP.decode(blockSigners) as [Uint8Array, Uint8Array][] return signers.map((s) => { - const blockNum = bufferToBigInt(s[0] as Buffer) + const blockNum = bytesToBigInt(s[0] as Uint8Array) const signer = new Address(s[1] as any) return [blockNum, signer] }) as CliqueLatestBlockSigners diff --git a/packages/blockchain/src/db/cache.ts b/packages/blockchain/src/db/cache.ts index d84a3459c8..9df9511420 100644 --- a/packages/blockchain/src/db/cache.ts +++ b/packages/blockchain/src/db/cache.ts @@ -1,7 +1,8 @@ +import { bytesToHex } from 'ethereum-cryptography/utils' import * as LRUCache from 'lru-cache' /** - * Simple LRU Cache that allows for keys of type Buffer + * Simple LRU Cache that allows for keys of type Uint8Array * @hidden */ export class Cache { @@ -11,23 +12,23 @@ export class Cache { this._cache = new LRUCache(opts) } - set(key: string | Buffer, value: V): void { - if (key instanceof Buffer) { - key = key.toString('hex') + set(key: string | Uint8Array, value: V): void { + if (key instanceof Uint8Array) { + key = bytesToHex(key) } this._cache.set(key, value) } - get(key: string | Buffer): V | undefined { - if (key instanceof Buffer) { - key = key.toString('hex') + get(key: string | Uint8Array): V | undefined { + if (key instanceof Uint8Array) { + key = bytesToHex(key) } return this._cache.get(key) } - del(key: string | Buffer): void { - if (key instanceof Buffer) { - key = key.toString('hex') + del(key: string | Uint8Array): void { + if (key instanceof Uint8Array) { + key = bytesToHex(key) } this._cache.del(key) } diff --git a/packages/blockchain/src/db/constants.ts b/packages/blockchain/src/db/constants.ts index 341b338bae..7bb6aa3bdf 100644 --- a/packages/blockchain/src/db/constants.ts +++ b/packages/blockchain/src/db/constants.ts @@ -1,4 +1,4 @@ -import { bigIntToBuffer } from '@ethereumjs/util' +import { bigIntToBytes, concatBytesNoTypeCheck, utf8ToBytes } from '@ethereumjs/util' // Geth compatible DB keys @@ -17,52 +17,55 @@ const HEAD_BLOCK_KEY = 'LastBlock' /** * headerPrefix + number + hash -> header */ -const HEADER_PREFIX = Buffer.from('h') +const HEADER_PREFIX = utf8ToBytes('h') /** * headerPrefix + number + hash + tdSuffix -> td */ -const TD_SUFFIX = Buffer.from('t') +const TD_SUFFIX = utf8ToBytes('t') /** * headerPrefix + number + numSuffix -> hash */ -const NUM_SUFFIX = Buffer.from('n') +const NUM_SUFFIX = utf8ToBytes('n') /** * blockHashPrefix + hash -> number */ -const BLOCK_HASH_PEFIX = Buffer.from('H') +const BLOCK_HASH_PEFIX = utf8ToBytes('H') /** * bodyPrefix + number + hash -> block body */ -const BODY_PREFIX = Buffer.from('b') +const BODY_PREFIX = utf8ToBytes('b') // Utility functions /** - * Convert bigint to big endian Buffer + * Convert bigint to big endian Uint8Array */ -const bufBE8 = (n: bigint) => bigIntToBuffer(BigInt.asUintN(64, n)) +const bytesBE8 = (n: bigint) => bigIntToBytes(BigInt.asUintN(64, n)) -const tdKey = (n: bigint, hash: Buffer) => - Buffer.concat([HEADER_PREFIX, bufBE8(n), hash, TD_SUFFIX]) +const tdKey = (n: bigint, hash: Uint8Array) => + concatBytesNoTypeCheck(HEADER_PREFIX, bytesBE8(n), hash, TD_SUFFIX) -const headerKey = (n: bigint, hash: Buffer) => Buffer.concat([HEADER_PREFIX, bufBE8(n), hash]) +const headerKey = (n: bigint, hash: Uint8Array) => + concatBytesNoTypeCheck(HEADER_PREFIX, bytesBE8(n), hash) -const bodyKey = (n: bigint, hash: Buffer) => Buffer.concat([BODY_PREFIX, bufBE8(n), hash]) +const bodyKey = (n: bigint, hash: Uint8Array) => + concatBytesNoTypeCheck(BODY_PREFIX, bytesBE8(n), hash) -const numberToHashKey = (n: bigint) => Buffer.concat([HEADER_PREFIX, bufBE8(n), NUM_SUFFIX]) +const numberToHashKey = (n: bigint) => + concatBytesNoTypeCheck(HEADER_PREFIX, bytesBE8(n), NUM_SUFFIX) -const hashToNumberKey = (hash: Buffer) => Buffer.concat([BLOCK_HASH_PEFIX, hash]) +const hashToNumberKey = (hash: Uint8Array) => concatBytesNoTypeCheck(BLOCK_HASH_PEFIX, hash) /** * @hidden */ export { bodyKey, - bufBE8, + bytesBE8, hashToNumberKey, HEAD_BLOCK_KEY, HEAD_HEADER_KEY, diff --git a/packages/blockchain/src/db/helpers.ts b/packages/blockchain/src/db/helpers.ts index c7146b050f..c55a19716c 100644 --- a/packages/blockchain/src/db/helpers.ts +++ b/packages/blockchain/src/db/helpers.ts @@ -1,8 +1,7 @@ import { Block } from '@ethereumjs/block' import { RLP } from '@ethereumjs/rlp' -import { bufArrToArr } from '@ethereumjs/util' -import { bufBE8 } from './constants' +import { bytesBE8 } from './constants' import { DBOp, DBTarget } from './operation' import type { BlockHeader } from '@ethereumjs/block' @@ -12,8 +11,8 @@ import type { BlockHeader } from '@ethereumjs/block' * and the DB operations from `db/operation.ts` and also handles the right encoding of the keys */ -function DBSetTD(TD: bigint, blockNumber: bigint, blockHash: Buffer): DBOp { - return DBOp.set(DBTarget.TotalDifficulty, Buffer.from(RLP.encode(TD)), { +function DBSetTD(TD: bigint, blockNumber: bigint, blockHash: Uint8Array): DBOp { + return DBOp.set(DBTarget.TotalDifficulty, RLP.encode(TD), { blockNumber, blockHash, }) @@ -50,7 +49,7 @@ function DBSetBlockOrHeader(blockBody: Block | BlockHeader): DBOp[] { (blockBody.withdrawals?.length ?? 0) || blockBody.uncleHeaders.length)) ) { - const bodyValue = Buffer.from(RLP.encode(bufArrToArr(blockBody.raw()).slice(1))) + const bodyValue = RLP.encode(blockBody.raw().slice(1)) dbOps.push( DBOp.set(DBTarget.Body, bodyValue, { blockNumber, @@ -62,20 +61,20 @@ function DBSetBlockOrHeader(blockBody: Block | BlockHeader): DBOp[] { return dbOps } -function DBSetHashToNumber(blockHash: Buffer, blockNumber: bigint): DBOp { - const blockNumber8Byte = bufBE8(blockNumber) +function DBSetHashToNumber(blockHash: Uint8Array, blockNumber: bigint): DBOp { + const blockNumber8Byte = bytesBE8(blockNumber) return DBOp.set(DBTarget.HashToNumber, blockNumber8Byte, { blockHash, }) } -function DBSaveLookups(blockHash: Buffer, blockNumber: bigint, skipNumIndex?: boolean): DBOp[] { +function DBSaveLookups(blockHash: Uint8Array, blockNumber: bigint, skipNumIndex?: boolean): DBOp[] { const ops = [] if (skipNumIndex !== true) { ops.push(DBOp.set(DBTarget.NumberToHash, blockHash, { blockNumber })) } - const blockNumber8Bytes = bufBE8(blockNumber) + const blockNumber8Bytes = bytesBE8(blockNumber) ops.push( DBOp.set(DBTarget.HashToNumber, blockNumber8Bytes, { blockHash, diff --git a/packages/blockchain/src/db/manager.ts b/packages/blockchain/src/db/manager.ts index 98a806c1fc..d84911091a 100644 --- a/packages/blockchain/src/db/manager.ts +++ b/packages/blockchain/src/db/manager.ts @@ -1,12 +1,12 @@ import { Block, BlockHeader, valuesArrayToHeaderData } from '@ethereumjs/block' import { RLP } from '@ethereumjs/rlp' -import { KECCAK256_RLP, KECCAK256_RLP_ARRAY, arrToBufArr, bufferToBigInt } from '@ethereumjs/util' +import { KECCAK256_RLP, KECCAK256_RLP_ARRAY, bytesToBigInt, equalsBytes } from '@ethereumjs/util' import { Cache } from './cache' import { DBOp, DBTarget } from './operation' import type { DBOpData, DatabaseKey } from './operation' -import type { BlockBodyBuffer, BlockBuffer, BlockOptions } from '@ethereumjs/block' +import type { BlockBodyBytes, BlockBytes, BlockOptions } from '@ethereumjs/block' import type { Common } from '@ethereumjs/common' import type { AbstractLevel } from 'abstract-level' @@ -32,7 +32,7 @@ export interface GetOpts { cache?: string } -export type CacheMap = { [key: string]: Cache } +export type CacheMap = { [key: string]: Cache } /** * Abstraction over a DB to facilitate storing/fetching blockchain-related @@ -42,10 +42,10 @@ export type CacheMap = { [key: string]: Cache } export class DBManager { private _cache: CacheMap private _common: Common - private _db: AbstractLevel + private _db: AbstractLevel constructor( - db: AbstractLevel, + db: AbstractLevel, common: Common ) { this._db = db @@ -62,10 +62,10 @@ export class DBManager { /** * Fetches iterator heads from the db. */ - async getHeads(): Promise<{ [key: string]: Buffer }> { + async getHeads(): Promise<{ [key: string]: Uint8Array }> { const heads = await this.get(DBTarget.Heads) for (const key of Object.keys(heads)) { - heads[key] = Buffer.from(heads[key]) + heads[key] = Uint8Array.from(heads[key]) } return heads } @@ -73,14 +73,14 @@ export class DBManager { /** * Fetches header of the head block. */ - async getHeadHeader(): Promise { + async getHeadHeader(): Promise { return this.get(DBTarget.HeadHeader) } /** * Fetches head block. */ - async getHeadBlock(): Promise { + async getHeadBlock(): Promise { return this.get(DBTarget.HeadBlock) } @@ -88,14 +88,14 @@ export class DBManager { * Fetches a block (header and body) given a block id, * which can be either its hash or its number. */ - async getBlock(blockId: Buffer | bigint | number): Promise { + async getBlock(blockId: Uint8Array | bigint | number): Promise { if (typeof blockId === 'number' && Number.isInteger(blockId)) { blockId = BigInt(blockId) } let number let hash - if (Buffer.isBuffer(blockId)) { + if (blockId instanceof Uint8Array) { hash = blockId number = await this.hashToNumber(blockId) } else if (typeof blockId === 'bigint') { @@ -106,7 +106,7 @@ export class DBManager { } const header = await this.getHeader(hash, number) - let body: BlockBodyBuffer + let body: BlockBodyBytes try { body = await this.getBody(hash, number) } catch (error: any) { @@ -116,8 +116,8 @@ export class DBManager { // Do extra validations on the header since we are assuming empty transactions and uncles if ( - !header.transactionsTrie.equals(KECCAK256_RLP) || - !header.uncleHash.equals(KECCAK256_RLP_ARRAY) + !equalsBytes(header.transactionsTrie, KECCAK256_RLP) || + !equalsBytes(header.uncleHash, KECCAK256_RLP_ARRAY) ) { throw error } @@ -125,14 +125,14 @@ export class DBManager { // If this block had empty withdrawals push an empty array in body if (header.withdrawalsRoot !== undefined) { // Do extra validations for withdrawal before assuming empty withdrawals - if (!header.withdrawalsRoot.equals(KECCAK256_RLP)) { + if (!equalsBytes(header.withdrawalsRoot, KECCAK256_RLP)) { throw error } body.push([]) } } - const blockData = [header.raw(), ...body] as BlockBuffer + const blockData = [header.raw(), ...body] as BlockBytes const opts: BlockOptions = { common: this._common } if (number === BigInt(0)) { opts.hardforkByTTD = await this.getTotalDifficulty(hash, BigInt(0)) @@ -145,17 +145,17 @@ export class DBManager { /** * Fetches body of a block given its hash and number. */ - async getBody(blockHash: Buffer, blockNumber: bigint): Promise { + async getBody(blockHash: Uint8Array, blockNumber: bigint): Promise { const body = await this.get(DBTarget.Body, { blockHash, blockNumber }) - return arrToBufArr(RLP.decode(Uint8Array.from(body))) as BlockBodyBuffer + return RLP.decode(body) as BlockBodyBytes } /** * Fetches header of a block given its hash and number. */ - async getHeader(blockHash: Buffer, blockNumber: bigint) { + async getHeader(blockHash: Uint8Array, blockNumber: bigint) { const encodedHeader = await this.get(DBTarget.Header, { blockHash, blockNumber }) - const headerValues = arrToBufArr(RLP.decode(Uint8Array.from(encodedHeader))) + const headerValues = RLP.decode(encodedHeader) const opts: BlockOptions = { common: this._common } if (blockNumber === BigInt(0)) { @@ -163,33 +163,33 @@ export class DBManager { } else { // Lets fetch the parent hash but not by number since this block might not // be in canonical chain - const headerData = valuesArrayToHeaderData(headerValues as Buffer[]) - const parentHash = headerData.parentHash as Buffer + const headerData = valuesArrayToHeaderData(headerValues as Uint8Array[]) + const parentHash = headerData.parentHash as Uint8Array opts.hardforkByTTD = await this.getTotalDifficulty(parentHash, blockNumber - BigInt(1)) } - return BlockHeader.fromValuesArray(headerValues as Buffer[], opts) + return BlockHeader.fromValuesArray(headerValues as Uint8Array[], opts) } /** * Fetches total difficulty for a block given its hash and number. */ - async getTotalDifficulty(blockHash: Buffer, blockNumber: bigint): Promise { + async getTotalDifficulty(blockHash: Uint8Array, blockNumber: bigint): Promise { const td = await this.get(DBTarget.TotalDifficulty, { blockHash, blockNumber }) - return bufferToBigInt(Buffer.from(RLP.decode(Uint8Array.from(td)) as Uint8Array)) + return bytesToBigInt(RLP.decode(td) as Uint8Array) } /** * Performs a block hash to block number lookup. */ - async hashToNumber(blockHash: Buffer): Promise { + async hashToNumber(blockHash: Uint8Array): Promise { const value = await this.get(DBTarget.HashToNumber, { blockHash }) - return bufferToBigInt(value) + return bytesToBigInt(value) } /** * Performs a block number to block hash lookup. */ - async numberToHash(blockNumber: bigint): Promise { + async numberToHash(blockNumber: bigint): Promise { if (blockNumber < BigInt(0)) { throw new NotFoundError(blockNumber) } diff --git a/packages/blockchain/src/db/operation.ts b/packages/blockchain/src/db/operation.ts index 53c70fef20..4a6cfa9c1a 100644 --- a/packages/blockchain/src/db/operation.ts +++ b/packages/blockchain/src/db/operation.ts @@ -31,16 +31,16 @@ export enum DBTarget { */ export interface DBOpData { type?: string - key: Buffer | string + key: Uint8Array | string keyEncoding: string valueEncoding?: string - value?: Buffer | object + value?: Uint8Array | object } // a Database Key is identified by a block hash, a block number, or both export type DatabaseKey = { blockNumber?: bigint - blockHash?: Buffer + blockHash?: Uint8Array } /** @@ -56,8 +56,8 @@ export class DBOp { this.baseDBOp = { key: '', - keyEncoding: 'buffer', - valueEncoding: 'buffer', + keyEncoding: 'view', + valueEncoding: 'view', } switch (operationTarget) { @@ -107,7 +107,11 @@ export class DBOp { } // set operation: note: value/key is not in default order - public static set(operationTarget: DBTarget, value: Buffer | object, key?: DatabaseKey): DBOp { + public static set( + operationTarget: DBTarget, + value: Uint8Array | object, + key?: DatabaseKey + ): DBOp { const dbOperation = new DBOp(operationTarget, key) dbOperation.baseDBOp.value = value dbOperation.baseDBOp.type = 'put' @@ -130,7 +134,7 @@ export class DBOp { public updateCache(cacheMap: CacheMap) { if (this.cacheString !== undefined && cacheMap[this.cacheString] !== undefined) { if (this.baseDBOp.type === 'put') { - Buffer.isBuffer(this.baseDBOp.value) && + this.baseDBOp.value instanceof Uint8Array && cacheMap[this.cacheString].set(this.baseDBOp.key, this.baseDBOp.value) } else if (this.baseDBOp.type === 'del') { cacheMap[this.cacheString].del(this.baseDBOp.key) diff --git a/packages/blockchain/src/genesisStates/index.ts b/packages/blockchain/src/genesisStates/index.ts index 9a00414fa8..838daf9fd0 100644 --- a/packages/blockchain/src/genesisStates/index.ts +++ b/packages/blockchain/src/genesisStates/index.ts @@ -1,7 +1,8 @@ import { RLP } from '@ethereumjs/rlp' import { Trie } from '@ethereumjs/trie' -import { Account, isHexPrefixed, toBuffer, unpadBuffer } from '@ethereumjs/util' +import { Account, isHexPrefixed, toBytes, unpadBytes } from '@ethereumjs/util' import { keccak256 } from 'ethereum-cryptography/keccak' +import { hexToBytes } from 'ethereum-cryptography/utils' import type { PrefixedHexString } from '@ethereumjs/util' @@ -23,7 +24,7 @@ export interface GenesisState { export async function genesisStateRoot(genesisState: GenesisState) { const trie = new Trie({ useKeyHashing: true }) for (const [key, value] of Object.entries(genesisState)) { - const address = isHexPrefixed(key) ? toBuffer(key) : Buffer.from(key, 'hex') + const address = isHexPrefixed(key) ? toBytes(key) : hexToBytes(key) const account = new Account() if (typeof value === 'string') { account.balance = BigInt(value) @@ -33,18 +34,14 @@ export async function genesisStateRoot(genesisState: GenesisState) { account.balance = BigInt(balance) } if (code !== undefined) { - account.codeHash = Buffer.from(keccak256(toBuffer(code))) + account.codeHash = keccak256(toBytes(code)) } if (storage !== undefined) { const storageTrie = new Trie({ useKeyHashing: true }) for (const [k, val] of storage) { - const storageKey = isHexPrefixed(k) ? toBuffer(k) : Buffer.from(k, 'hex') - const storageVal = Buffer.from( - RLP.encode( - Uint8Array.from( - unpadBuffer(isHexPrefixed(val) ? toBuffer(val) : Buffer.from(val, 'hex')) - ) - ) + const storageKey = isHexPrefixed(k) ? toBytes(k) : hexToBytes(k) + const storageVal = RLP.encode( + unpadBytes(isHexPrefixed(val) ? toBytes(val) : hexToBytes(val)) ) await storageTrie.put(storageKey, storageVal) } diff --git a/packages/blockchain/src/types.ts b/packages/blockchain/src/types.ts index cdbfb13859..a1396722af 100644 --- a/packages/blockchain/src/types.ts +++ b/packages/blockchain/src/types.ts @@ -21,12 +21,12 @@ export interface BlockchainInterface { * * @param blockHash - The hash of the block to be deleted */ - delBlock(blockHash: Buffer): Promise + delBlock(blockHash: Uint8Array): Promise /** * Returns a block by its hash or number. */ - getBlock(blockId: Buffer | number | bigint): Promise + getBlock(blockId: Uint8Array | number | bigint): Promise /** * Iterates through blocks starting at the specified iterator head and calls @@ -66,7 +66,7 @@ export interface BlockchainInterface { /** * Gets total difficulty for a block specified by hash and number */ - getTotalDifficulty?(hash: Buffer, number?: bigint): Promise + getTotalDifficulty?(hash: Uint8Array, number?: bigint): Promise /** * Returns the genesis state of the blockchain. @@ -112,7 +112,7 @@ export interface BlockchainOptions { * or use the `level` convenience package: * `new MemoryLevel('./db1')` */ - db?: AbstractLevel + db?: AbstractLevel /** * This flags indicates if a block should be validated along the consensus algorithm diff --git a/packages/blockchain/test/blockValidation.spec.ts b/packages/blockchain/test/blockValidation.spec.ts index 014e8e790a..af2d5bca64 100644 --- a/packages/blockchain/test/blockValidation.spec.ts +++ b/packages/blockchain/test/blockValidation.spec.ts @@ -1,9 +1,8 @@ import { Block, BlockHeader } from '@ethereumjs/block' import { Chain, Common, Hardfork } from '@ethereumjs/common' import { RLP } from '@ethereumjs/rlp' -import { bufArrToArr } from '@ethereumjs/util' +import { bytesToPrefixedHexString } from '@ethereumjs/util' import { keccak256 } from 'ethereum-cryptography/keccak' -import { bytesToHex } from 'ethereum-cryptography/utils' import * as tape from 'tape' import { Blockchain } from '../src' @@ -335,8 +334,9 @@ tape('[Blockchain]: Block validation tests', (t) => { common: new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Berlin }), }) - forkBlockHeaderData.uncleHash = - '0x' + bytesToHex(keccak256(RLP.encode(bufArrToArr([uncleHeader.raw()])))) + forkBlockHeaderData.uncleHash = bytesToPrefixedHexString( + keccak256(RLP.encode([uncleHeader.raw()])) + ) const forkBlock_ValidCommon = Block.fromBlockData( { @@ -348,8 +348,9 @@ tape('[Blockchain]: Block validation tests', (t) => { } ) - st.ok( - forkBlock_ValidCommon.uncleHeaders[0].hash().equals(uncleHeader.hash()), + st.deepEquals( + forkBlock_ValidCommon.uncleHeaders[0].hash(), + uncleHeader.hash(), 'successfully validated a pre-london uncle on a london block' ) st.equal(common.hardfork(), Hardfork.London, 'validation did not change common hardfork') diff --git a/packages/blockchain/test/clique.spec.ts b/packages/blockchain/test/clique.spec.ts index 23a673fdda..4cd8801f93 100644 --- a/packages/blockchain/test/clique.spec.ts +++ b/packages/blockchain/test/clique.spec.ts @@ -1,6 +1,7 @@ import { Block } from '@ethereumjs/block' import { Chain, Common, ConsensusAlgorithm, ConsensusType, Hardfork } from '@ethereumjs/common' import { Address } from '@ethereumjs/util' +import { concatBytes, equalsBytes, hexToBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' import { Blockchain } from '../src' @@ -15,7 +16,7 @@ tape('Clique: Initialization', (t) => { const blockchain = await Blockchain.create({ common }) const head = await blockchain.getIteratorHead() - st.ok(head.hash().equals(blockchain.genesisBlock.hash()), 'correct genesis hash') + st.ok(equalsBytes(head.hash(), blockchain.genesisBlock.hash()), 'correct genesis hash') st.deepEquals( (blockchain.consensus as CliqueConsensus).cliqueActiveSigners(), @@ -26,84 +27,60 @@ tape('Clique: Initialization', (t) => { }) const COMMON = new Common({ chain: Chain.Rinkeby, hardfork: Hardfork.Chainstart }) - const EXTRA_DATA = Buffer.alloc(97) + const EXTRA_DATA = new Uint8Array(97) const GAS_LIMIT = BigInt(8000000) type Signer = { address: Address - privateKey: Buffer - publicKey: Buffer + privateKey: Uint8Array + publicKey: Uint8Array } const A: Signer = { - address: new Address(Buffer.from('0b90087d864e82a284dca15923f3776de6bb016f', 'hex')), - privateKey: Buffer.from( - '64bf9cc30328b0e42387b3c82c614e6386259136235e20c1357bd11cdee86993', - 'hex' - ), - publicKey: Buffer.from( - '40b2ebdf4b53206d2d3d3d59e7e2f13b1ea68305aec71d5d24cefe7f24ecae886d241f9267f04702d7f693655eb7b4aa23f30dcd0c3c5f2b970aad7c8a828195', - 'hex' + address: new Address(hexToBytes('0b90087d864e82a284dca15923f3776de6bb016f')), + privateKey: hexToBytes('64bf9cc30328b0e42387b3c82c614e6386259136235e20c1357bd11cdee86993'), + publicKey: hexToBytes( + '40b2ebdf4b53206d2d3d3d59e7e2f13b1ea68305aec71d5d24cefe7f24ecae886d241f9267f04702d7f693655eb7b4aa23f30dcd0c3c5f2b970aad7c8a828195' ), } const B: Signer = { - address: new Address(Buffer.from('6f62d8382bf2587361db73ceca28be91b2acb6df', 'hex')), - privateKey: Buffer.from( - '2a6e9ad5a6a8e4f17149b8bc7128bf090566a11dbd63c30e5a0ee9f161309cd6', - 'hex' - ), - publicKey: Buffer.from( - 'ca0a55f6e81cb897aee6a1c390aa83435c41048faa0564b226cfc9f3df48b73e846377fb0fd606df073addc7bd851f22547afbbdd5c3b028c91399df802083a2', - 'hex' + address: new Address(hexToBytes('6f62d8382bf2587361db73ceca28be91b2acb6df')), + privateKey: hexToBytes('2a6e9ad5a6a8e4f17149b8bc7128bf090566a11dbd63c30e5a0ee9f161309cd6'), + publicKey: hexToBytes( + 'ca0a55f6e81cb897aee6a1c390aa83435c41048faa0564b226cfc9f3df48b73e846377fb0fd606df073addc7bd851f22547afbbdd5c3b028c91399df802083a2' ), } const C: Signer = { - address: new Address(Buffer.from('83c30730d1972baa09765a1ac72a43db27fedce5', 'hex')), - privateKey: Buffer.from( - 'f216ddcf276079043c52b5dd144aa073e6b272ad4bfeaf4fbbc044aa478d1927', - 'hex' - ), - publicKey: Buffer.from( - '555b19a5cbe6dd082a4a1e1e0520dd52a82ba24fd5598ea31f0f31666c40905ed319314c5fb06d887b760229e1c0e616294e7b1cb5dfefb71507c9112132ce56', - 'hex' + address: new Address(hexToBytes('83c30730d1972baa09765a1ac72a43db27fedce5')), + privateKey: hexToBytes('f216ddcf276079043c52b5dd144aa073e6b272ad4bfeaf4fbbc044aa478d1927'), + publicKey: hexToBytes( + '555b19a5cbe6dd082a4a1e1e0520dd52a82ba24fd5598ea31f0f31666c40905ed319314c5fb06d887b760229e1c0e616294e7b1cb5dfefb71507c9112132ce56' ), } const D: Signer = { - address: new Address(Buffer.from('8458f408106c4875c96679f3f556a511beabe138', 'hex')), - privateKey: Buffer.from( - '159e95d07a6c64ddbafa6036cdb7b8114e6e8cdc449ca4b0468a6d0c955f991b', - 'hex' - ), - publicKey: Buffer.from( - 'f02724341e2df54cf53515f079b1354fa8d437e79c5b091b8d8cc7cbcca00fd8ad854cb3b3a85b06c44ecb7269404a67be88b561f2224c94d133e5fc21be915c', - 'hex' + address: new Address(hexToBytes('8458f408106c4875c96679f3f556a511beabe138')), + privateKey: hexToBytes('159e95d07a6c64ddbafa6036cdb7b8114e6e8cdc449ca4b0468a6d0c955f991b'), + publicKey: hexToBytes( + 'f02724341e2df54cf53515f079b1354fa8d437e79c5b091b8d8cc7cbcca00fd8ad854cb3b3a85b06c44ecb7269404a67be88b561f2224c94d133e5fc21be915c' ), } const E: Signer = { - address: new Address(Buffer.from('ab80a948c661aa32d09952d2a6c4ad77a4c947be', 'hex')), - privateKey: Buffer.from( - '48ec5a6c4a7fc67b10a9d4c8a8f594a81ae42e41ed061fa5218d96abb6012344', - 'hex' - ), - publicKey: Buffer.from( - 'adefb82b9f54e80aa3532263e4478739de16fcca6828f4ae842f8a07941c347fa59d2da1300569237009f0f122dc1fd6abb0db8fcb534280aa94948a5cc95f94', - 'hex' + address: new Address(hexToBytes('ab80a948c661aa32d09952d2a6c4ad77a4c947be')), + privateKey: hexToBytes('48ec5a6c4a7fc67b10a9d4c8a8f594a81ae42e41ed061fa5218d96abb6012344'), + publicKey: hexToBytes( + 'adefb82b9f54e80aa3532263e4478739de16fcca6828f4ae842f8a07941c347fa59d2da1300569237009f0f122dc1fd6abb0db8fcb534280aa94948a5cc95f94' ), } const F: Signer = { - address: new Address(Buffer.from('dc7bc81ddf67d037d7439f8e6ff12f3d2a100f71', 'hex')), - privateKey: Buffer.from( - '86b0ff7b6cf70786f29f297c57562905ab0b6c32d69e177a46491e56da9e486e', - 'hex' - ), - publicKey: Buffer.from( - 'd3e3d2b722e325bfc085ff5638a112b4e7e88ff13f92fc7f6cfc14b5a25e8d1545a2f27d8537b96e8919949d5f8c139ae7fc81aea7cf7fe5d43d7faaa038e35b', - 'hex' + address: new Address(hexToBytes('dc7bc81ddf67d037d7439f8e6ff12f3d2a100f71')), + privateKey: hexToBytes('86b0ff7b6cf70786f29f297c57562905ab0b6c32d69e177a46491e56da9e486e'), + publicKey: hexToBytes( + 'd3e3d2b722e325bfc085ff5638a112b4e7e88ff13f92fc7f6cfc14b5a25e8d1545a2f27d8537b96e8919949d5f8c139ae7fc81aea7cf7fe5d43d7faaa038e35b' ), } @@ -111,11 +88,11 @@ tape('Clique: Initialization', (t) => { common = common ?? COMMON const blocks: Block[] = [] - const extraData = Buffer.concat([ - Buffer.alloc(32), - ...signers.map((s) => s.address.toBuffer()), - Buffer.alloc(65), - ]) + const extraData = concatBytes( + new Uint8Array(32), + ...signers.map((s) => s.address.toBytes()), + new Uint8Array(65) + ) const genesisBlock = Block.fromBlockData( { header: { gasLimit: GAS_LIMIT, extraData } }, { common } @@ -152,11 +129,11 @@ tape('Clique: Initialization', (t) => { nonce = CLIQUE_NONCE_AUTH } } else if (checkpointSigners) { - extraData = Buffer.concat([ - Buffer.alloc(32), - ...checkpointSigners.map((s) => s.address.toBuffer()), - Buffer.alloc(65), - ]) + extraData = concatBytes( + new Uint8Array(32), + ...checkpointSigners.map((s) => s.address.toBytes()), + new Uint8Array(65) + ) } const blockData = { @@ -195,12 +172,12 @@ tape('Clique: Initialization', (t) => { ;(blockchain as any)._validateConsensus = true const number = (COMMON.consensusConfig() as CliqueConfig).epoch const unauthorizedSigner = Address.fromString('0x00a839de7922491683f547a67795204763ff8237') - const extraData = Buffer.concat([ - Buffer.alloc(32), - A.address.toBuffer(), - unauthorizedSigner.toBuffer(), - Buffer.alloc(65), - ]) + const extraData = concatBytes( + new Uint8Array(32), + A.address.toBytes(), + unauthorizedSigner.toBytes(), + new Uint8Array(65) + ) const block = Block.fromBlockData( { header: { number, extraData } }, { common: COMMON, cliqueSigner: A.privateKey } @@ -225,7 +202,7 @@ tape('Clique: Initialization', (t) => { await addNextBlock(blockchain, blocks, A) const parentHeader = await blockchain.getCanonicalHeadHeader() const number = BigInt(2) - const extraData = Buffer.alloc(97) + const extraData = new Uint8Array(97) let difficulty = BigInt(5) let block = Block.fromBlockData( { @@ -292,7 +269,7 @@ tape('Clique: Initialization', (t) => { // noturn block await addNextBlock(blockchain, blocks, A) const block = await blockchain.getBlock(1) - if (inturnBlock.hash().equals(block.hash())) { + if (equalsBytes(inturnBlock.hash(), block.hash())) { st.pass('correct canonical block') } else { st.fail('invalid canonical block') diff --git a/packages/blockchain/test/customConsensus.spec.ts b/packages/blockchain/test/customConsensus.spec.ts index 479c179720..d385eee7f6 100644 --- a/packages/blockchain/test/customConsensus.spec.ts +++ b/packages/blockchain/test/customConsensus.spec.ts @@ -1,5 +1,6 @@ import { Block } from '@ethereumjs/block' import { Common, Hardfork } from '@ethereumjs/common' +import { bytesToHex } from 'ethereum-cryptography/utils' import * as tape from 'tape' import { Blockchain, EthashConsensus } from '../src' @@ -19,7 +20,7 @@ class fibonacciConsensus implements Consensus { return new Promise((resolve) => resolve()) } validateConsensus(_block: Block): Promise { - if (_block.header.extraData.toString('hex') !== '12358d') { + if (bytesToHex(_block.header.extraData) !== '12358d') { throw new Error( 'header contains invalid extradata - must match first 6 elements of fibonacci sequence' ) diff --git a/packages/blockchain/test/index.spec.ts b/packages/blockchain/test/index.spec.ts index a1fb958af7..7238639bc9 100644 --- a/packages/blockchain/test/index.spec.ts +++ b/packages/blockchain/test/index.spec.ts @@ -1,5 +1,6 @@ import { Block, BlockHeader } from '@ethereumjs/block' import { Chain, Common, Hardfork } from '@ethereumjs/common' +import { bytesToHex, equalsBytes, hexToBytes, utf8ToBytes } from 'ethereum-cryptography/utils' import { MemoryLevel } from 'memory-level' import * as tape from 'tape' @@ -27,8 +28,9 @@ tape('blockchain test', (t) => { const iteratorHead = await blockchain.getIteratorHead() - st.ok( - iteratorHead.hash().equals(blockchain.genesisBlock.hash()), + st.deepEquals( + iteratorHead.hash(), + blockchain.genesisBlock.hash(), 'correct genesis hash (getIteratorHead())' ) @@ -76,8 +78,9 @@ tape('blockchain test', (t) => { validateConsensus: false, genesisBlock, }) - st.ok( - genesisBlock.hash().equals((await blockchain.getCanonicalHeadHeader()).hash()), + st.deepEquals( + genesisBlock.hash(), + (await blockchain.getCanonicalHeadHeader()).hash(), 'genesis block hash should be correct' ) st.end() @@ -185,7 +188,7 @@ tape('blockchain test', (t) => { const returnedBlock = await blockchain.getBlock(1) if (typeof returnedBlock !== 'undefined') { - st.ok(returnedBlock.hash().equals(blocks[1].hash())) + st.deepEquals(returnedBlock.hash(), blocks[1].hash()) } else { st.fail('block is not defined!') } @@ -204,7 +207,7 @@ tape('blockchain test', (t) => { genesisBlock, }) const block = await blockchain.getBlock(genesisBlock.hash()) - st.ok(block.hash().equals(genesisBlock.hash())) + st.deepEquals(block.hash(), genesisBlock.hash()) try { await blockchain.getBlock(5) @@ -214,7 +217,7 @@ tape('blockchain test', (t) => { } try { - await blockchain.getBlock(Buffer.from('1234', 'hex')) + await blockchain.getBlock(hexToBytes('1234')) st.fail('should throw an exception') } catch (e: any) { st.ok(e.message.includes('NotFound'), `should throw for non-existing block-by-hash request`) @@ -262,8 +265,8 @@ tape('blockchain test', (t) => { const newblock22 = await blockchain.getBlock(22) st.equal(newblock22.header.number, BigInt(22), 'canonical references should be restored') st.equal( - newblock22.hash().toString('hex'), - newblock22.hash().toString('hex'), + bytesToHex(newblock22.hash()), + bytesToHex(newblock22.hash()), 'fetched block should match' ) const newheader22 = await blockchain.getCanonicalHeader(BigInt(22)) @@ -406,13 +409,13 @@ tape('blockchain test', (t) => { t.test('should find needed hashes', async (st) => { const { blockchain, blocks, error } = await generateBlockchain(25) st.error(error, 'no error') - const neededHash = Buffer.from('abcdef', 'hex') + const neededHash = hexToBytes('abcdef') const hashes = await blockchain.selectNeededHashes([ blocks[0].hash(), blocks[9].hash(), neededHash, ]) - st.ok(hashes[0].equals(neededHash)) + st.deepEquals(hashes[0], neededHash) st.end() }) @@ -438,8 +441,8 @@ tape('blockchain test', (t) => { await blockchain.putHeader(forkHeader) - st.ok(blockchain._heads['staletest'].equals(blocks[14].hash()), 'should update stale head') - st.ok(blockchain._headBlockHash.equals(blocks[14].hash()), 'should update stale headBlock') + st.deepEquals(blockchain._heads['staletest'], blocks[14].hash(), 'should update stale head') + st.deepEquals(blockchain._headBlockHash, blocks[14].hash(), 'should update stale headBlock') st.end() }) @@ -464,13 +467,13 @@ tape('blockchain test', (t) => { await blockchain.putHeader(forkHeader) - st.ok(blockchain._heads['staletest'].equals(blocks[14].hash()), 'should update stale head') - st.ok(blockchain._headBlockHash.equals(blocks[14].hash()), 'should update stale headBlock') + st.deepEquals(blockchain._heads['staletest'], blocks[14].hash(), 'should update stale head') + st.deepEquals(blockchain._headBlockHash, blocks[14].hash(), 'should update stale headBlock') await blockchain.delBlock(forkHeader.hash()) - st.ok(blockchain._headHeaderHash.equals(blocks[14].hash()), 'should reset headHeader') - st.ok(blockchain._headBlockHash.equals(blocks[14].hash()), 'should not change headBlock') + st.deepEquals(blockchain._headHeaderHash, blocks[14].hash(), 'should reset headHeader') + st.deepEquals(blockchain._headBlockHash, blocks[14].hash(), 'should not change headBlock') st.end() }) @@ -487,7 +490,7 @@ tape('blockchain test', (t) => { } await delNextBlock(9) - st.ok(blockchain._headHeaderHash.equals(blocks[5].hash()), 'should have block 5 as head') + st.deepEquals(blockchain._headHeaderHash, blocks[5].hash(), 'should have block 5 as head') st.end() }) @@ -495,7 +498,7 @@ tape('blockchain test', (t) => { const { blockchain, blocks, error } = await generateBlockchain(25) st.error(error, 'no error') await blockchain.delBlock(blocks[1].hash()) - st.ok(blockchain._headHeaderHash.equals(blocks[0].hash()), 'should have genesis as head') + st.deepEquals(blockchain._headHeaderHash, blocks[0].hash(), 'should have genesis as head') st.end() }) @@ -524,7 +527,7 @@ tape('blockchain test', (t) => { await blockchain.getBlock(BigInt(1)) const block2HeaderValuesArray = blocks[2].header.raw() - block2HeaderValuesArray[1] = Buffer.alloc(32) + block2HeaderValuesArray[1] = new Uint8Array(32) const block2Header = BlockHeader.fromValuesArray(block2HeaderValuesArray, { common: blocks[2]._common, }) @@ -572,7 +575,7 @@ tape('blockchain test', (t) => { t.test('should add block with body', async (st) => { const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Istanbul }) - const genesisRlp = Buffer.from(testDataPreLondon.genesisRLP.slice(2), 'hex') + const genesisRlp = hexToBytes(testDataPreLondon.genesisRLP.slice(2)) const genesisBlock = Block.fromRLPSerializedBlock(genesisRlp, { common }) const blockchain = await Blockchain.create({ validateBlocks: true, @@ -580,7 +583,7 @@ tape('blockchain test', (t) => { genesisBlock, }) - const blockRlp = Buffer.from(testDataPreLondon.blocks[0].rlp.slice(2), 'hex') + const blockRlp = hexToBytes(testDataPreLondon.blocks[0].rlp.slice(2)) const block = Block.fromRLPSerializedBlock(blockRlp, { common }) await blockchain.putBlock(block) st.end() @@ -597,7 +600,7 @@ tape('blockchain test', (t) => { st.equal(number, BigInt(0), 'should perform _hashToNumber correctly') const hash = await blockchain.dbManager.numberToHash(BigInt(0)) - st.ok(genesis.hash().equals(hash), 'should perform _numberToHash correctly') + st.deepEquals(genesis.hash(), hash, 'should perform _numberToHash correctly') // cast the blockchain as in order to get access to the private getTotalDifficulty const td = await (blockchain).getTotalDifficulty(genesis.hash(), BigInt(0)) @@ -606,7 +609,7 @@ tape('blockchain test', (t) => { }) t.test('should save headers', async (st) => { - const db = new MemoryLevel() + const db = new MemoryLevel() const gasLimit = 8000000 const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Istanbul }) @@ -638,10 +641,10 @@ tape('blockchain test', (t) => { }) const latestHeader = await blockchain.getCanonicalHeadHeader() - st.ok(latestHeader.hash().equals(header.hash()), 'should save headHeader') + st.deepEquals(latestHeader.hash(), header.hash(), 'should save headHeader') const latestBlock = await blockchain.getCanonicalHeadBlock() - st.ok(latestBlock.hash().equals(genesisBlock.hash()), 'should save headBlock') + st.deepEquals(latestBlock.hash(), genesisBlock.hash(), 'should save headBlock') st.end() }) @@ -691,18 +694,18 @@ tape('blockchain test', (t) => { await blockchain.putHeaders(headers) const latestHeader = await blockchain.getCanonicalHeadHeader() - st.ok(latestHeader.hash().equals(headers[1].hash()), 'should update latest header') + st.deepEquals(latestHeader.hash(), headers[1].hash(), 'should update latest header') const latestBlock = await blockchain.getCanonicalHeadBlock() - st.ok(latestBlock.hash().equals(genesisBlock.hash()), 'should not change latest block') + st.deepEquals(latestBlock.hash(), genesisBlock.hash(), 'should not change latest block') await blockchain.putBlock(block) const latestHeader2 = await blockchain.getCanonicalHeadHeader() - st.ok(latestHeader2.hash().equals(headers[1].hash()), 'should not change latest header') + st.deepEquals(latestHeader2.hash(), headers[1].hash(), 'should not change latest header') const getBlock = await blockchain.getCanonicalHeadBlock() - st.ok(getBlock!.hash().equals(block.hash()), 'should update latest block') + st.deepEquals(getBlock!.hash(), block.hash(), 'should update latest block') st.end() }) @@ -768,8 +771,9 @@ tape('initialization tests', (t) => { const blockchain = await Blockchain.create({ common }) const genesisHash = blockchain.genesisBlock.hash() - st.ok( - (await blockchain.getIteratorHead()).hash().equals(genesisHash), + st.deepEquals( + (await blockchain.getIteratorHead()).hash(), + genesisHash, 'head hash should equal expected ropsten genesis hash' ) @@ -777,8 +781,9 @@ tape('initialization tests', (t) => { const newBlockchain = await Blockchain.create({ db, common }) - st.ok( - (await newBlockchain.getIteratorHead()).hash().equals(genesisHash), + st.deepEquals( + (await newBlockchain.getIteratorHead()).hash(), + genesisHash, 'head hash should be read from the provided db' ) st.end() @@ -789,7 +794,7 @@ tape('initialization tests', (t) => { const genesisBlock = Block.fromBlockData( { header: { - extraData: Buffer.from('custom extra data'), + extraData: utf8ToBytes('custom extra data'), }, }, { common } @@ -798,14 +803,16 @@ tape('initialization tests', (t) => { const blockchain = await Blockchain.create({ common, genesisBlock }) const db = blockchain.db - st.ok( - (await blockchain.getIteratorHead()).hash().equals(hash), + st.deepEquals( + (await blockchain.getIteratorHead()).hash(), + hash, 'blockchain should put custom genesis block' ) const newBlockchain = await Blockchain.create({ db, genesisBlock }) - st.ok( - (await newBlockchain.getIteratorHead()).hash().equals(hash), + st.deepEquals( + (await newBlockchain.getIteratorHead()).hash(), + hash, 'head hash should be read from the provided db' ) st.end() @@ -816,7 +823,7 @@ tape('initialization tests', (t) => { const genesisBlock = Block.fromBlockData( { header: { - extraData: Buffer.from('custom extra data'), + extraData: utf8ToBytes('custom extra data'), }, }, { common } @@ -828,14 +835,14 @@ tape('initialization tests', (t) => { const otherGenesisBlock = Block.fromBlockData( { header: { - extraData: Buffer.from('other extra data'), + extraData: utf8ToBytes('other extra data'), }, }, { common } ) // assert that this is a block with a new hash - if (otherGenesisBlock.hash().equals(hash)) { + if (equalsBytes(otherGenesisBlock.hash(), hash)) { st.fail('other genesis block should have a different hash than the genesis block') } @@ -861,16 +868,14 @@ tape('initialization tests', (t) => { t.test('should correctly derive ropsten genesis block hash and stateRoot', async (st) => { const common = new Common({ chain: Chain.Ropsten }) const blockchain = await Blockchain.create({ common }) - const ropstenGenesisBlockHash = Buffer.from( - '41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d', - 'hex' + const ropstenGenesisBlockHash = hexToBytes( + '41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d' ) - const ropstenGenesisStateRoot = Buffer.from( - '217b0bbcfb72e2d57e28f33cb361b9983513177755dc3f33ce3e7022ed62b77b', - 'hex' + const ropstenGenesisStateRoot = hexToBytes( + '217b0bbcfb72e2d57e28f33cb361b9983513177755dc3f33ce3e7022ed62b77b' ) - st.ok(blockchain.genesisBlock.hash().equals(ropstenGenesisBlockHash)) - st.ok(blockchain.genesisBlock.header.stateRoot.equals(ropstenGenesisStateRoot)) + st.deepEquals(blockchain.genesisBlock.hash(), ropstenGenesisBlockHash) + st.deepEquals(blockchain.genesisBlock.header.stateRoot, ropstenGenesisStateRoot) st.end() }) }) diff --git a/packages/blockchain/test/iterator.spec.ts b/packages/blockchain/test/iterator.spec.ts index 58bb2fbf44..b13f81bf08 100644 --- a/packages/blockchain/test/iterator.spec.ts +++ b/packages/blockchain/test/iterator.spec.ts @@ -1,3 +1,4 @@ +import { bytesToHex, equalsBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' import { Blockchain } from '../src' @@ -14,7 +15,7 @@ tape('blockchain test', (t) => { let reorged = 0 const iterated = await blockchain.iterator('test', (block: Block, reorg: boolean) => { if (reorg) reorged++ - if (block.hash().equals(blocks[i + 1].hash())) { + if (equalsBytes(block.hash(), blocks[i + 1].hash()) === true) { i++ } }) @@ -51,7 +52,7 @@ tape('blockchain test', (t) => { await blockchain.putBlocks(reorgedBlocks) } } else { - if (block.hash().equals(reorgedBlocks[Number(block.header.number) - 5].hash())) { + if (equalsBytes(block.hash(), reorgedBlocks[Number(block.header.number) - 5].hash())) { servedReorged++ } } @@ -59,7 +60,7 @@ tape('blockchain test', (t) => { undefined, true ) - st.equal(reorged, 1, ' should have reorged once') + st.equal(reorged, 1, 'should have reorged once') st.equal( servedReorged, reorgedBlocks.length, @@ -78,7 +79,7 @@ tape('blockchain test', (t) => { const iterated = await blockchain.iterator( 'test', (block: Block) => { - if (block.hash().equals(blocks[i + 1].hash())) { + if (equalsBytes(block.hash(), blocks[i + 1].hash())) { i++ } }, @@ -100,7 +101,7 @@ tape('blockchain test', (t) => { .iterator( 'test', (block: Block) => { - if (block.hash().equals(blocks[i + 1].hash())) { + if (equalsBytes(block.hash(), blocks[i + 1].hash())) { i++ } }, @@ -123,7 +124,7 @@ tape('blockchain test', (t) => { .iterator( 'test', (block: Block) => { - if (block.hash().equals(blocks[i + 1].hash())) { + if (equalsBytes(block.hash(), blocks[i + 1].hash())) { i++ } }, @@ -145,14 +146,14 @@ tape('blockchain test', (t) => { await blockchain.setIteratorHead('myHead', headHash) const currentHeadBlock = await blockchain.getIteratorHead('myHead') - st.ok(headHash.equals(currentHeadBlock.hash()), 'head hash equals the provided head hash') + st.deepEquals(headHash, currentHeadBlock.hash(), 'head hash equals the provided head hash') let i = 0 // check that iterator starts from this head block await blockchain.iterator( 'myHead', (block: Block) => { - if (block.hash().equals(blocks[headBlockIndex + 1].hash())) { + if (equalsBytes(block.hash(), blocks[headBlockIndex + 1].hash())) { i++ } }, @@ -196,10 +197,11 @@ tape('blockchain test', (t) => { const [db, genesis] = await createTestDB() const blockchain = await Blockchain.create({ db, genesisBlock: genesis }) const head = await blockchain.getIteratorHead() + if (typeof genesis !== 'undefined') { - st.ok(head.hash().equals(genesis.hash()), 'should get head') + st.deepEquals(head.hash(), genesis.hash(), 'should get head') st.equal( - (blockchain as any)._heads['head0'].toString('hex'), + bytesToHex((blockchain as any)._heads['head0']), 'abcd', 'should get state root heads' ) diff --git a/packages/blockchain/test/pos.spec.ts b/packages/blockchain/test/pos.spec.ts index 9c3daa75db..af4581efe9 100644 --- a/packages/blockchain/test/pos.spec.ts +++ b/packages/blockchain/test/pos.spec.ts @@ -1,5 +1,6 @@ import { Block } from '@ethereumjs/block' import { Chain, Common, Hardfork } from '@ethereumjs/common' +import { bytesToHex } from 'ethereum-cryptography/utils' import * as tape from 'tape' import { Blockchain } from '../src' @@ -64,7 +65,7 @@ tape('Proof of Stake - inserting blocks into blockchain', async (t) => { }) const genesisHeader = await blockchain.getCanonicalHeadHeader() t.equal( - genesisHeader.hash().toString('hex'), + bytesToHex(genesisHeader.hash()), '1119dc5ff680bf7b4c3d9cd41168334dee127d46b3626482076025cdd498ed0b', 'genesis hash matches' ) diff --git a/packages/blockchain/test/reorg.spec.ts b/packages/blockchain/test/reorg.spec.ts index fdc642c702..3b141c9c0f 100644 --- a/packages/blockchain/test/reorg.spec.ts +++ b/packages/blockchain/test/reorg.spec.ts @@ -1,6 +1,7 @@ import { Block } from '@ethereumjs/block' import { Chain, Common, Hardfork } from '@ethereumjs/common' import { Address } from '@ethereumjs/util' +import { equalsBytes, hexToBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' import { Blockchain } from '../src' @@ -71,7 +72,7 @@ tape('reorg tests', (t) => { async (st) => { const common = new Common({ chain: Chain.Goerli, hardfork: Hardfork.Chainstart }) const genesisBlock = Block.fromBlockData( - { header: { extraData: Buffer.alloc(97) } }, + { header: { extraData: new Uint8Array(97) } }, { common } ) const blockchain = await Blockchain.create({ @@ -81,16 +82,15 @@ tape('reorg tests', (t) => { genesisBlock, }) - const extraData = Buffer.from( - '506172697479205465636820417574686f7269747900000000000000000000002bbf886181970654ed46e3fae0ded41ee53fec702c47431988a7ae80e6576f3552684f069af80ba11d36327aaf846d470526e4a1c461601b2fd4ebdcdc2b734a01', - 'hex' + const extraData = hexToBytes( + '506172697479205465636820417574686f7269747900000000000000000000002bbf886181970654ed46e3fae0ded41ee53fec702c47431988a7ae80e6576f3552684f069af80ba11d36327aaf846d470526e4a1c461601b2fd4ebdcdc2b734a01' ) // from goerli block 1 const { gasLimit } = genesisBlock.header const base = { extraData, gasLimit, difficulty: 1 } const nonce = CLIQUE_NONCE_AUTH - const beneficiary1 = new Address(Buffer.alloc(20).fill(1)) - const beneficiary2 = new Address(Buffer.alloc(20).fill(2)) + const beneficiary1 = new Address(new Uint8Array(20).fill(1)) + const beneficiary2 = new Address(new Uint8Array(20).fill(2)) const block1_low = Block.fromBlockData( { @@ -158,6 +158,7 @@ tape('reorg tests', (t) => { await blockchain.putBlocks([block1_high, block2_high, block3_high]) let signerStates = (blockchain.consensus as CliqueConsensus)._cliqueLatestSignerStates + t.ok( !signerStates.find( (s: any) => s[0] === BigInt(2) && s[1].find((a: Address) => a.equals(beneficiary1)) @@ -172,7 +173,7 @@ tape('reorg tests', (t) => { v[0] === BigInt(2) && v[1][0].equals(block1_low.header.cliqueSigner()) && v[1][1].equals(beneficiary1) && - v[1][2].equals(CLIQUE_NONCE_AUTH) + equalsBytes(v[1][2], CLIQUE_NONCE_AUTH) ), 'should not find reorged clique vote' ) diff --git a/packages/blockchain/test/util.ts b/packages/blockchain/test/util.ts index b8d7286c80..3c66a11a77 100644 --- a/packages/blockchain/test/util.ts +++ b/packages/blockchain/test/util.ts @@ -1,8 +1,9 @@ import { Block, BlockHeader } from '@ethereumjs/block' import { Chain, Common, Hardfork } from '@ethereumjs/common' import { RLP } from '@ethereumjs/rlp' -import { bufArrToArr, toBuffer } from '@ethereumjs/util' +import { toBytes } from '@ethereumjs/util' import { keccak256 } from 'ethereum-cryptography/keccak' +import { equalsBytes, hexToBytes, utf8ToBytes } from 'ethereum-cryptography/utils' import { MemoryLevel } from 'memory-level' import { Blockchain } from '../src' @@ -110,7 +111,7 @@ export const isConsecutive = (blocks: Block[]) => { } const { parentHash } = block.header const lastBlockHash = blocks[index - 1].hash() - return !parentHash.equals(lastBlockHash) + return !equalsBytes(parentHash, lastBlockHash) }) } @@ -121,67 +122,64 @@ export const createTestDB = async (): Promise<[Level, Block]> => { await db.batch([ { type: 'put', - key: Buffer.from('6800000000000000006e', 'hex'), - keyEncoding: 'buffer', - valueEncoding: 'buffer', + key: hexToBytes('6800000000000000006e'), + keyEncoding: 'view', + valueEncoding: 'view', value: genesis.hash(), }, { type: 'put', - key: Buffer.from('48d4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3', 'hex'), - keyEncoding: 'buffer', - valueEncoding: 'buffer', - value: Buffer.from('00', 'hex'), + key: hexToBytes('48d4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3'), + keyEncoding: 'view', + valueEncoding: 'view', + value: hexToBytes('00'), }, { type: 'put', key: 'LastHeader', - keyEncoding: 'buffer', - valueEncoding: 'buffer', + keyEncoding: 'view', + valueEncoding: 'view', value: genesis.hash(), }, { type: 'put', key: 'LastBlock', - keyEncoding: 'buffer', - valueEncoding: 'buffer', + keyEncoding: 'view', + valueEncoding: 'view', value: genesis.hash(), }, { type: 'put', - key: Buffer.from( - '680000000000000000d4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3', - 'hex' + key: hexToBytes( + '680000000000000000d4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3' ), - keyEncoding: 'buffer', - valueEncoding: 'buffer', + keyEncoding: 'view', + valueEncoding: 'view', value: genesis.header.serialize(), }, { type: 'put', - key: Buffer.from( - '680000000000000000d4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa374', - 'hex' + key: hexToBytes( + '680000000000000000d4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa374' ), - keyEncoding: 'buffer', - valueEncoding: 'buffer', - value: Buffer.from(RLP.encode(Uint8Array.from(toBuffer(17179869184)))), + keyEncoding: 'view', + valueEncoding: 'view', + value: RLP.encode(toBytes(17179869184)), }, { type: 'put', - key: Buffer.from( - '620000000000000000d4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3', - 'hex' + key: hexToBytes( + '620000000000000000d4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3' ), - keyEncoding: 'buffer', - valueEncoding: 'buffer', - value: Buffer.from(RLP.encode(bufArrToArr(genesis.raw()).slice(1))), + keyEncoding: 'view', + valueEncoding: 'view', + value: RLP.encode(genesis.raw().slice(1)), }, { type: 'put', key: 'heads', valueEncoding: 'json', - value: { head0: { type: 'Buffer', data: [171, 205] } }, + value: { head0: [171, 205] }, }, ]) return [db as any, genesis] @@ -209,7 +207,7 @@ function createBlock( const number = parentBlock.header.number + BigInt(1) const timestamp = parentBlock.header.timestamp + BigInt(1) - const uncleHash = keccak256(RLP.encode(bufArrToArr(uncles.map((uh) => uh.raw())))) + const uncleHash = keccak256(RLP.encode(uncles.map((uh) => uh.raw()))) const londonHfBlock = common.hardforkBlock(Hardfork.London) const baseFeePerGas = @@ -224,7 +222,7 @@ function createBlock( parentHash: parentBlock.hash(), timestamp, gasLimit: parentBlock.header.gasLimit, - extraData: Buffer.from(extraData), + extraData: utf8ToBytes(extraData), uncleHash, baseFeePerGas, }, diff --git a/packages/blockchain/test/utils.spec.ts b/packages/blockchain/test/utils.spec.ts index 364df4cc8c..47a9f85938 100644 --- a/packages/blockchain/test/utils.spec.ts +++ b/packages/blockchain/test/utils.spec.ts @@ -1,4 +1,5 @@ import { Common } from '@ethereumjs/common' +import { bytesToHex } from 'ethereum-cryptography/utils' import * as tape from 'tape' import { Blockchain } from '../src/blockchain' @@ -22,7 +23,7 @@ tape('[Utils/Parse]', (t) => { const genesisState = parseGethGenesisState(json) const stateRoot = await genesisStateRoot(genesisState) t.equal( - stateRoot.toString('hex'), + bytesToHex(stateRoot), '52e628c7f35996ba5a0402d02b34535993c89ff7fc4c430b2763ada8554bee62', 'kiln stateRoot matches' ) @@ -35,7 +36,7 @@ tape('[Utils/Parse]', (t) => { const genesisHash = blockchain.genesisBlock.hash() t.equal( - genesisHash.toString('hex'), + bytesToHex(genesisHash), '51c7fe41be669f69c45c33a56982cbde405313342d9e2b00d7c91a7b284dd4f8', 'kiln genesis hash matches' ) diff --git a/packages/client/bin/cli.ts b/packages/client/bin/cli.ts index 55d2026028..54ba708795 100755 --- a/packages/client/bin/cli.ts +++ b/packages/client/bin/cli.ts @@ -5,9 +5,16 @@ 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, arrToBufArr, short, toBuffer } from '@ethereumjs/util' +import { + Address, + bytesToHex, + bytesToPrefixedHexString, + hexStringToBytes, + randomBytes, + short, + toBytes, +} from '@ethereumjs/util' import * as kzg from 'c-kzg' -import { randomBytes } from 'crypto' import { existsSync, writeFileSync } from 'fs' import { ensureDirSync, readFileSync, removeSync } from 'fs-extra' import { Level } from 'level' @@ -27,14 +34,14 @@ import type { Logger } from '../lib/logging' import type { FullEthereumService } from '../lib/service' import type { ClientOpts } from '../lib/types' import type { RPCArgs } from './startRpc' -import type { BlockBuffer } from '@ethereumjs/block' +import type { BlockBytes } from '@ethereumjs/block' import type { GenesisState } from '@ethereumjs/blockchain/dist/genesisStates' import type { AbstractLevel } from 'abstract-level' const { hideBin } = require('yargs/helpers') const yargs = require('yargs/yargs') -type Account = [address: Address, privateKey: Buffer] +type Account = [address: Address, privateKey: Uint8Array] const networks = Object.entries(Common._getInitializedChains().names) @@ -311,24 +318,24 @@ const args: ClientOpts = yargs(hideBin(process.argv)) * Initializes and returns the databases needed for the client */ function initDBs(config: Config): { - chainDB: AbstractLevel - stateDB: AbstractLevel - metaDB: AbstractLevel + chainDB: AbstractLevel + stateDB: AbstractLevel + metaDB: AbstractLevel } { // Chain DB const chainDataDir = config.getDataDirectory(DataDirectory.Chain) ensureDirSync(chainDataDir) - const chainDB = new Level(chainDataDir) + const chainDB = new Level(chainDataDir) // State DB const stateDataDir = config.getDataDirectory(DataDirectory.State) ensureDirSync(stateDataDir) - const stateDB = new Level(stateDataDir) + const stateDB = new Level(stateDataDir) // Meta DB (receipts, logs, indexes, skeleton chain) const metaDataDir = config.getDataDirectory(DataDirectory.Meta) ensureDirSync(metaDataDir) - const metaDB = new Level(metaDataDir) + const metaDB = new Level(metaDataDir) return { chainDB, stateDB, metaDB } } @@ -447,14 +454,14 @@ async function startClient(config: Config, customGenesisState?: GenesisState) { let buf = RLP.decode(blockRlp, true) while (buf.data?.length > 0 || buf.remainder?.length > 0) { try { - const block = Block.fromValuesArray(arrToBufArr(buf.data) as unknown as BlockBuffer, { + const block = Block.fromValuesArray(buf.data as BlockBytes, { common: config.chainCommon, hardforkByBlockNumber: true, }) blocks.push(block) buf = RLP.decode(buf.remainder, true) config.logger.info( - `Preloading block hash=0x${short(block.header.hash().toString('hex'))} number=${ + `Preloading block hash=0x${short(bytesToHex(block.header.hash()))} number=${ block.header.number }` ) @@ -574,7 +581,7 @@ async function inputAccounts() { `Please enter the 0x-prefixed private key to unlock ${address}:\n` ) ;(rl as any).history = (rl as any).history.slice(1) - const privKey = toBuffer(inputKey) + const privKey = toBytes(inputKey) const derivedAddress = Address.fromPrivateKey(privKey) if (address.equals(derivedAddress)) { accounts.push([address, privKey]) @@ -587,7 +594,7 @@ async function inputAccounts() { } } else { const acc = readFileSync(path.resolve(args.unlock!), 'utf-8') - const privKey = Buffer.from(acc, 'hex') + const privKey = hexStringToBytes(acc) const derivedAddress = Address.fromPrivateKey(privKey) accounts.push([derivedAddress, privKey]) } @@ -608,7 +615,7 @@ function generateAccount(): Account { console.log('='.repeat(50)) console.log('Account generated for mining blocks:') console.log(`Address: ${address}`) - console.log(`Private key: 0x${privKey.toString('hex')}`) + console.log(`Private key: ${bytesToPrefixedHexString(privKey)}`) console.log('WARNING: Do not use this account for mainnet funds') console.log('='.repeat(50)) return [address, privKey] @@ -746,7 +753,7 @@ async function run() { config.logger.error(`Error writing listener details to disk: ${(e as Error).message}`) } }) - if (customGenesisState) { + if (customGenesisState !== undefined) { const numAccounts = Object.keys(customGenesisState).length config.logger.info(`Reading custom genesis state accounts=${numAccounts}`) } diff --git a/packages/client/bin/startRpc.ts b/packages/client/bin/startRpc.ts index fa6bab0f80..2f6ba9c77f 100644 --- a/packages/client/bin/startRpc.ts +++ b/packages/client/bin/startRpc.ts @@ -1,3 +1,5 @@ +import { hexStringToBytes, randomBytes } from '@ethereumjs/util' +import { bytesToHex } from 'ethereum-cryptography/utils' import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs' import { RPCManager, saveReceiptsMethods } from '../lib/rpc' @@ -35,8 +37,8 @@ export type RPCArgs = { /** * Returns a jwt secret from a provided file path, otherwise saves a randomly generated one to datadir if none already exists */ -function parseJwtSecret(config: Config, jwtFilePath?: string): Buffer { - let jwtSecret: Buffer +function parseJwtSecret(config: Config, jwtFilePath?: string): Uint8Array { + let jwtSecret: Uint8Array const defaultJwtPath = `${config.datadir}/jwtsecret` const usedJwtPath = jwtFilePath !== undefined ? jwtFilePath : defaultJwtPath @@ -52,15 +54,15 @@ function parseJwtSecret(config: Config, jwtFilePath?: string): Buffer { if (jwtSecretHex === undefined || jwtSecretHex.length !== 64) { throw Error('Need a valid 256 bit hex encoded secret') } - jwtSecret = Buffer.from(jwtSecretHex, 'hex') + jwtSecret = hexStringToBytes(jwtSecretHex) } else { const folderExists = existsSync(config.datadir) if (!folderExists) { mkdirSync(config.datadir, { recursive: true }) } - jwtSecret = Buffer.from(Array.from({ length: 32 }, () => Math.round(Math.random() * 255))) - writeFileSync(defaultJwtPath, jwtSecret.toString('hex'), {}) + jwtSecret = randomBytes(32) + writeFileSync(defaultJwtPath, bytesToHex(jwtSecret), {}) config.logger.info(`New Engine API JWT token created path=${defaultJwtPath}`) } config.logger.info(`Using Engine API with JWT token authentication path=${usedJwtPath}`) @@ -93,7 +95,7 @@ export function startRPCServers(client: EthereumClient, args: RPCArgs) { const manager = new RPCManager(client, config) const { logger } = config const jwtSecret = - rpcEngine && rpcEngineAuth ? parseJwtSecret(config, jwtSecretPath) : Buffer.from([]) + rpcEngine && rpcEngineAuth ? parseJwtSecret(config, jwtSecretPath) : new Uint8Array(0) let withEngineMethods = false if ((rpc || rpcEngine) && !config.saveReceipts) { diff --git a/packages/client/browser/index.ts b/packages/client/browser/index.ts index 1b218ebac7..71744f2191 100644 --- a/packages/client/browser/index.ts +++ b/packages/client/browser/index.ts @@ -70,7 +70,9 @@ export async function createClient(args: any) { discDns: false, }) config.events.setMaxListeners(50) - const chainDB = new Level(`${datadir}/${common.chainName()}`) + const chainDB = new Level( + `${datadir}/${common.chainName()}` + ) const blockchain = await Blockchain.create({ db: chainDB, diff --git a/packages/client/browser/util/index.ts b/packages/client/browser/util/index.ts index dac3e915d1..3a28e37796 100644 --- a/packages/client/browser/util/index.ts +++ b/packages/client/browser/util/index.ts @@ -1,18 +1,19 @@ /** * @module util */ +import { bytesToPrefixedHexString } from '@ethereumjs/util' import { platform } from 'os' import { version as packageVersion } from '../../package.json' export * from '../../lib/util/parse' -export function short(buf: Buffer | string): string { - if (buf === null || buf === undefined || buf === '') return '' - const bufStr = Buffer.isBuffer(buf) ? `0x${buf.toString('hex')}` : buf - let str = bufStr.substring(0, 6) + '…' - if (bufStr.length === 66) { - str += bufStr.substring(62) +export function short(bytes: Uint8Array | string): string { + if (bytes === null || bytes === undefined || bytes === '') return '' + const bytesString = bytes instanceof Uint8Array ? bytesToPrefixedHexString(bytes) : bytes + let str = bytesString.substring(0, 6) + '…' + if (bytesString.length === 66) { + str += bytesString.substring(62) } return str } diff --git a/packages/client/devnets/4844-interop/tools/txGenerator.ts b/packages/client/devnets/4844-interop/tools/txGenerator.ts index d92da6c03f..16dd356693 100644 --- a/packages/client/devnets/4844-interop/tools/txGenerator.ts +++ b/packages/client/devnets/4844-interop/tools/txGenerator.ts @@ -6,16 +6,16 @@ import { commitmentsToVersionedHashes, getBlobs, } from '@ethereumjs/tx/dist/utils/blobHelpers' -import { Address } from '@ethereumjs/util' +import { Address, bytesToPrefixedHexString, hexStringToBytes } from '@ethereumjs/util' import * as kzg from 'c-kzg' -import { randomBytes } from 'crypto' +import { randomBytes } from '@ethereumjs/util' import { Client } from 'jayson/promise' // CLI Args const clientPort = parseInt(process.argv[2]) // EL client port number const input = process.argv[3] // text to generate blob from const genesisJson = require(process.argv[4]) // Genesis parameters -const pkey = Buffer.from(process.argv[5], 'hex') // private key of tx sender as unprefixed hex string +const pkey = hexStringToBytes(process.argv[5]) // private key of tx sender as unprefixed hex string initKZG(kzg, __dirname + '/../../../lib/trustedSetups/devnet4.txt') @@ -65,7 +65,7 @@ async function run(data: any) { const res = await client.request( 'eth_sendRawTransaction', - ['0x' + serializedWrapper.toString('hex')], + [bytesToPrefixedHexString(serializedWrapper)], 2.0 ) diff --git a/packages/client/lib/blockchain/chain.ts b/packages/client/lib/blockchain/chain.ts index a5fbe9388b..134293ea87 100644 --- a/packages/client/lib/blockchain/chain.ts +++ b/packages/client/lib/blockchain/chain.ts @@ -1,6 +1,7 @@ import { Block, BlockHeader } from '@ethereumjs/block' import { Blockchain } from '@ethereumjs/blockchain' import { ConsensusAlgorithm, Hardfork } from '@ethereumjs/common' +import { equalsBytes } from 'ethereum-cryptography/utils' import { Event } from '../types' @@ -19,7 +20,7 @@ export interface ChainOptions { /** * Database to store blocks and metadata. Should be an abstract-leveldown compliant store. */ - chainDB?: AbstractLevel + chainDB?: AbstractLevel /** * Specify a blockchain which implements the Chain interface @@ -97,7 +98,7 @@ export interface ChainHeaders { */ export class Chain { public config: Config - public chainDB: AbstractLevel + public chainDB: AbstractLevel public blockchain: Blockchain public opened: boolean @@ -338,7 +339,12 @@ export class Chain { * @param reverse get blocks in reverse * @returns an array of the blocks */ - async getBlocks(block: Buffer | bigint, max = 1, skip = 0, reverse = false): Promise { + async getBlocks( + block: Uint8Array | bigint, + max = 1, + skip = 0, + reverse = false + ): Promise { if (!this.opened) throw new Error('Chain closed') return this.blockchain.getBlocks(block, max, skip, reverse) } @@ -348,7 +354,7 @@ export class Chain { * @param block block hash or number * @throws if block is not found */ - async getBlock(block: Buffer | bigint): Promise { + async getBlock(block: Uint8Array | bigint): Promise { if (!this.opened) throw new Error('Chain closed') return this.blockchain.getBlock(block) } @@ -369,7 +375,7 @@ export class Chain { for (const block of blocks) { if (this.headers.finalized !== null && block.header.number <= this.headers.finalized.number) { const canonicalBlock = await this.getBlock(block.header.number) - if (!canonicalBlock.hash().equals(block.hash())) { + if (!equalsBytes(canonicalBlock.hash(), block.hash())) { throw Error( `Invalid putBlock for block=${block.header.number} before finalized=${this.headers.finalized.number}` ) @@ -416,7 +422,7 @@ export class Chain { * @returns list of block headers */ async getHeaders( - block: Buffer | bigint, + block: Uint8Array | bigint, max: number, skip: number, reverse: boolean @@ -494,7 +500,7 @@ export class Chain { * @param num the block number * @returns the td */ - async getTd(hash: Buffer, num: bigint): Promise { + async getTd(hash: Uint8Array, num: bigint): Promise { if (!this.opened) throw new Error('Chain closed') return this.blockchain.getTotalDifficulty(hash, num) } diff --git a/packages/client/lib/client.ts b/packages/client/lib/client.ts index d114c88bff..817da52231 100644 --- a/packages/client/lib/client.ts +++ b/packages/client/lib/client.ts @@ -23,7 +23,7 @@ export interface EthereumClientOptions { * * Default: Database created by the Blockchain class */ - chainDB?: AbstractLevel + chainDB?: AbstractLevel /** * Database to store the state. @@ -31,7 +31,7 @@ export interface EthereumClientOptions { * * Default: Database created by the Trie class */ - stateDB?: AbstractLevel + stateDB?: AbstractLevel /** * Database to store tx receipts, logs, and indexes. @@ -39,7 +39,7 @@ export interface EthereumClientOptions { * * Default: Database created in datadir folder */ - metaDB?: AbstractLevel + metaDB?: AbstractLevel /* List of bootnodes to use for discovery */ bootnodes?: MultiaddrLike[] diff --git a/packages/client/lib/config.ts b/packages/client/lib/config.ts index a1485804a1..571f64667f 100644 --- a/packages/client/lib/config.ts +++ b/packages/client/lib/config.ts @@ -83,7 +83,7 @@ export interface ConfigOptions { * Use return value of {@link Config.getClientKey}. * If left blank, a random key will be generated and used. */ - key?: Buffer + key?: Uint8Array /** * Network transports ('rlpx' and/or 'libp2p') @@ -236,7 +236,7 @@ export interface ConfigOptions { * * Default: [] */ - accounts?: [address: Address, privKey: Buffer][] + accounts?: [address: Address, privKey: Uint8Array][] /** * Address for mining rewards (etherbase) @@ -312,7 +312,7 @@ export class Config { public readonly vm?: VM public readonly lightserv: boolean public readonly datadir: string - public readonly key: Buffer + public readonly key: Uint8Array public readonly transports: string[] public readonly bootnodes?: Multiaddr[] public readonly port?: number @@ -332,7 +332,7 @@ export class Config { public readonly discV4: boolean public readonly mine: boolean public readonly isSingleNode: boolean - public readonly accounts: [address: Address, privKey: Buffer][] + public readonly accounts: [address: Address, privKey: Uint8Array][] public readonly minerCoinbase?: Address public readonly safeReorgDistance: number @@ -453,11 +453,14 @@ export class Config { return } - if (latest) { + if (latest !== null && latest !== undefined) { const height = latest.number if (height >= (this.syncTargetHeight ?? BigInt(0))) { this.syncTargetHeight = height - this.lastSyncDate = latest.timestamp ? Number(latest.timestamp) * 1000 : Date.now() + this.lastSyncDate = + typeof latest.timestamp === 'bigint' && latest.timestamp > 0n + ? Number(latest.timestamp) * 1000 + : Date.now() const diff = Date.now() - this.lastSyncDate // update synchronized @@ -491,7 +494,7 @@ export class Config { this.logger.debug( `Client synchronized=${this.synchronized}${ - latest ? ' height=' + latest.number : '' + latest !== null && latest !== undefined ? ' height=' + latest.number : '' } syncTargetHeight=${this.syncTargetHeight} lastSyncDate=${ (Date.now() - this.lastSyncDate) / 1000 } secs ago` @@ -527,7 +530,7 @@ export class Config { * Returns the config level db. */ static getConfigDB(networkDir: string) { - return new Level(`${networkDir}/config` as any) + return new Level(`${networkDir}/config` as any) } /** diff --git a/packages/client/lib/execution/execution.ts b/packages/client/lib/execution/execution.ts index 7045782a0f..c0c43c1ddd 100644 --- a/packages/client/lib/execution/execution.ts +++ b/packages/client/lib/execution/execution.ts @@ -7,10 +7,10 @@ export interface ExecutionOptions { config: Config /* State database */ - stateDB?: AbstractLevel + stateDB?: AbstractLevel /* Meta database (receipts, logs, indexes) */ - metaDB?: AbstractLevel + metaDB?: AbstractLevel /** Chain */ chain: Chain @@ -19,8 +19,8 @@ export interface ExecutionOptions { export abstract class Execution { public config: Config - protected stateDB?: AbstractLevel - protected metaDB?: AbstractLevel + protected stateDB?: AbstractLevel + protected metaDB?: AbstractLevel protected chain: Chain public running: boolean = false diff --git a/packages/client/lib/execution/level.ts b/packages/client/lib/execution/level.ts index a336f4513e..08398f739d 100644 --- a/packages/client/lib/execution/level.ts +++ b/packages/client/lib/execution/level.ts @@ -10,7 +10,7 @@ export const ENCODING_OPTS = { keyEncoding: 'buffer', valueEncoding: 'buffer' } * which validates inputs and sets encoding type. */ export class LevelDB implements DB { - _leveldb: AbstractLevel + _leveldb: AbstractLevel /** * Initialize a DB instance. If `leveldb` is not provided, DB @@ -18,7 +18,7 @@ export class LevelDB implements DB { * @param leveldb - An abstract-leveldown compliant store */ constructor( - leveldb?: AbstractLevel + leveldb?: AbstractLevel ) { this._leveldb = leveldb ?? new MemoryLevel(ENCODING_OPTS) } @@ -26,7 +26,7 @@ export class LevelDB implements DB { /** * @inheritDoc */ - async get(key: Buffer): Promise { + async get(key: Uint8Array): Promise { let value = null try { value = await this._leveldb.get(key, ENCODING_OPTS) @@ -38,20 +38,20 @@ export class LevelDB implements DB { throw error } } - return value as Buffer | null + return value as Uint8Array | null } /** * @inheritDoc */ - async put(key: Buffer, val: Buffer): Promise { + async put(key: Uint8Array, val: Uint8Array): Promise { await this._leveldb.put(key, val, ENCODING_OPTS) } /** * @inheritDoc */ - async del(key: Buffer): Promise { + async del(key: Uint8Array): Promise { await this._leveldb.del(key, ENCODING_OPTS) } diff --git a/packages/client/lib/execution/receipt.ts b/packages/client/lib/execution/receipt.ts index c5fb45b503..583f9568b1 100644 --- a/packages/client/lib/execution/receipt.ts +++ b/packages/client/lib/execution/receipt.ts @@ -1,11 +1,11 @@ import { RLP } from '@ethereumjs/rlp' import { - arrToBufArr, - bigIntToBuffer, - bufArrToArr, - bufferToBigInt, - bufferToInt, - intToBuffer, + bigIntToBytes, + bytesToBigInt, + bytesToInt, + equalsBytes, + intToBytes, + utf8ToBytes, } from '@ethereumjs/util' import { Bloom } from '@ethereumjs/vm' @@ -35,7 +35,7 @@ interface PostByzantiumTxReceiptWithType extends PostByzantiumTxReceipt { */ type GetReceiptByTxHashReturn = [ receipt: TxReceipt, - blockHash: Buffer, + blockHash: Uint8Array, txIndex: number, logIndex: number ] @@ -50,7 +50,7 @@ type GetLogsReturn = { /** * Indexes */ -type TxHashIndex = [blockHash: Buffer, txIndex: number] +type TxHashIndex = [blockHash: Uint8Array, txIndex: number] enum IndexType { TxHash, @@ -64,8 +64,8 @@ enum IndexOperation { * Storage encodings */ type rlpLog = Log -type rlpReceipt = [postStateOrStatus: Buffer, cumulativeGasUsed: Buffer, logs: rlpLog[]] -type rlpTxHash = [blockHash: Buffer, txIndex: Buffer] +type rlpReceipt = [postStateOrStatus: Uint8Array, cumulativeGasUsed: Uint8Array, logs: rlpLog[]] +type rlpTxHash = [blockHash: Uint8Array, txIndex: Uint8Array] enum RlpConvert { Encode, @@ -113,17 +113,17 @@ export class ReceiptsManager extends MetaDBManager { * @param includeTxType whether to include the tx type for each receipt (default: false) */ async getReceipts( - blockHash: Buffer, + blockHash: Uint8Array, calcBloom?: boolean, includeTxType?: true ): Promise async getReceipts( - blockHash: Buffer, + blockHash: Uint8Array, calcBloom?: boolean, includeTxType?: false ): Promise async getReceipts( - blockHash: Buffer, + blockHash: Uint8Array, calcBloom = false, includeTxType = false ): Promise { @@ -150,7 +150,7 @@ export class ReceiptsManager extends MetaDBManager { * Returns receipt by tx hash with additional metadata for the JSON RPC response, or null if not found * @param txHash the tx hash */ - async getReceiptByTxHash(txHash: Buffer): Promise { + async getReceiptByTxHash(txHash: Uint8Array): Promise { const txHashIndex = await this.getIndex(IndexType.TxHash, txHash) if (!txHashIndex) return null const [blockHash, txIndex] = txHashIndex @@ -169,8 +169,8 @@ export class ReceiptsManager extends MetaDBManager { async getLogs( from: Block, to: Block, - addresses?: Buffer[], - topics: (Buffer | Buffer[] | null)[] = [] + addresses?: Uint8Array[], + topics: (Uint8Array | Uint8Array[] | null)[] = [] ): Promise { const returnedLogs: GetLogsReturn = [] let returnedLogsSize = 0 @@ -192,7 +192,7 @@ export class ReceiptsManager extends MetaDBManager { ) } if (addresses && addresses.length > 0) { - logs = logs.filter((l) => addresses.some((a) => a.equals(l.log[0]))) + logs = logs.filter((l) => addresses.some((a) => equalsBytes(a, l.log[0]))) } if (topics.length > 0) { // From https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_newfilter/: @@ -207,19 +207,19 @@ export class ReceiptsManager extends MetaDBManager { for (const [i, topic] of topics.entries()) { if (Array.isArray(topic)) { // Can match any items in this array - if (!topic.find((t) => t.equals(l.log[1][i]))) return false + if (!topic.find((t) => equalsBytes(t, l.log[1][i]))) return false } else if (!topic) { // If null then can match any } else { // If a value is specified then it must match - if (!topic.equals(l.log[1][i])) return false + if (!equalsBytes(topic, l.log[1][i])) return false } return true } }) } returnedLogs.push(...logs) - returnedLogsSize += Buffer.byteLength(JSON.stringify(logs)) + returnedLogsSize += utf8ToBytes(JSON.stringify(logs)).byteLength if ( returnedLogs.length >= this.GET_LOGS_LIMIT || returnedLogsSize >= this.GET_LOGS_LIMIT_MEGABYTES * 1048576 @@ -280,8 +280,8 @@ export class ReceiptsManager extends MetaDBManager { * @param type the {@link IndexType} * @param value for {@link IndexType.TxHash}, the txHash to get */ - private async getIndex(type: IndexType.TxHash, value: Buffer): Promise - private async getIndex(type: IndexType, value: Buffer): Promise { + private async getIndex(type: IndexType.TxHash, value: Uint8Array): Promise + private async getIndex(type: IndexType, value: Uint8Array): Promise { switch (type) { case IndexType.TxHash: { const encoded = await this.get(DBKey.TxHash, value) @@ -299,29 +299,33 @@ export class ReceiptsManager extends MetaDBManager { * @param type one of {@link RlpType} * @param value the value to encode or decode */ - private rlp(conversion: RlpConvert.Encode, type: RlpType, value: rlpOut): Buffer - private rlp(conversion: RlpConvert.Decode, type: RlpType.Receipts, values: Buffer): TxReceipt[] + private rlp(conversion: RlpConvert.Encode, type: RlpType, value: rlpOut): Uint8Array + private rlp( + conversion: RlpConvert.Decode, + type: RlpType.Receipts, + values: Uint8Array + ): TxReceipt[] private rlp(conversion: RlpConvert.Decode, type: RlpType.Logs, value: rlpLog[]): Log[] - private rlp(conversion: RlpConvert.Decode, type: RlpType.TxHash, value: Buffer): TxHashIndex - private rlp(conversion: RlpConvert, type: RlpType, value: Buffer | rlpOut): Buffer | rlpOut { + private rlp(conversion: RlpConvert.Decode, type: RlpType.TxHash, value: Uint8Array): TxHashIndex + private rlp( + conversion: RlpConvert, + type: RlpType, + value: Uint8Array | rlpOut + ): Uint8Array | rlpOut { switch (type) { case RlpType.Receipts: if (conversion === RlpConvert.Encode) { value = value as TxReceipt[] - return Buffer.from( - RLP.encode( - bufArrToArr( - value.map((r) => [ - (r as PreByzantiumTxReceipt).stateRoot ?? - intToBuffer((r as PostByzantiumTxReceipt).status), - bigIntToBuffer(r.cumulativeBlockGasUsed), - this.rlp(RlpConvert.Encode, RlpType.Logs, r.logs), - ]) - ) - ) + return RLP.encode( + value.map((r) => [ + (r as PreByzantiumTxReceipt).stateRoot ?? + intToBytes((r as PostByzantiumTxReceipt).status), + bigIntToBytes(r.cumulativeBlockGasUsed), + this.rlp(RlpConvert.Encode, RlpType.Logs, r.logs), + ]) ) } else { - const decoded = arrToBufArr(RLP.decode(Uint8Array.from(value as Buffer))) as rlpReceipt[] + const decoded = RLP.decode(value as Uint8Array) as unknown as rlpReceipt[] return decoded.map((r) => { const gasUsed = r[1] const logs = this.rlp(RlpConvert.Decode, RlpType.Logs, r[2]) @@ -329,14 +333,14 @@ export class ReceiptsManager extends MetaDBManager { // Pre-Byzantium Receipt return { stateRoot: r[0], - cumulativeBlockGasUsed: bufferToBigInt(gasUsed), + cumulativeBlockGasUsed: bytesToBigInt(gasUsed), logs, } as PreByzantiumTxReceipt } else { // Post-Byzantium Receipt return { - status: bufferToInt(r[0]), - cumulativeBlockGasUsed: bufferToBigInt(gasUsed), + status: bytesToInt(r[0]), + cumulativeBlockGasUsed: bytesToBigInt(gasUsed), logs, } as PostByzantiumTxReceipt } @@ -344,19 +348,17 @@ export class ReceiptsManager extends MetaDBManager { } case RlpType.Logs: if (conversion === RlpConvert.Encode) { - return Buffer.from(RLP.encode(bufArrToArr(value as Log[]))) + return RLP.encode(value as Log[]) } else { - return arrToBufArr(RLP.decode(Uint8Array.from(value as Buffer))) as Log[] + return RLP.decode(value as Uint8Array) as Log[] } case RlpType.TxHash: if (conversion === RlpConvert.Encode) { const [blockHash, txIndex] = value as TxHashIndex - return Buffer.from(RLP.encode(bufArrToArr([blockHash, intToBuffer(txIndex)]))) + return RLP.encode([blockHash, intToBytes(txIndex)]) } else { - const [blockHash, txIndex] = arrToBufArr( - RLP.decode(Uint8Array.from(value as Buffer)) - ) as rlpTxHash - return [blockHash, bufferToInt(txIndex)] as TxHashIndex + const [blockHash, txIndex] = RLP.decode(value as Uint8Array) as unknown as rlpTxHash + return [blockHash, bytesToInt(txIndex)] as TxHashIndex } default: throw new Error('Unknown rlp conversion') diff --git a/packages/client/lib/execution/vmexecution.ts b/packages/client/lib/execution/vmexecution.ts index 40bc65305d..45114c38f0 100644 --- a/packages/client/lib/execution/vmexecution.ts +++ b/packages/client/lib/execution/vmexecution.ts @@ -7,7 +7,7 @@ import { import { ConsensusType, Hardfork } from '@ethereumjs/common' import { DefaultStateManager } from '@ethereumjs/statemanager' import { Trie } from '@ethereumjs/trie' -import { Lock, bufferToHex } from '@ethereumjs/util' +import { Lock, bytesToHex, bytesToPrefixedHexString, equalsBytes } from '@ethereumjs/util' import { VM } from '@ethereumjs/vm' import { Event } from '../types' @@ -138,7 +138,7 @@ export class VMExecution extends Execution { } if (receipts !== undefined) { // Save receipts - this.pendingReceipts?.set(block.hash().toString('hex'), receipts) + this.pendingReceipts?.set(bytesToHex(block.hash()), receipts) } // Bypass updating head by using blockchain db directly const [hash, num] = [block.hash(), block.header.number] @@ -202,10 +202,10 @@ export class VMExecution extends Execution { // skip emitting the chain update event as we will manually do it await this.chain.putBlocks(blocks, true, true) for (const block of blocks) { - const receipts = this.pendingReceipts?.get(block.hash().toString('hex')) + const receipts = this.pendingReceipts?.get(bytesToHex(block.hash())) if (receipts) { void this.receiptsManager?.saveReceipts(block, receipts) - this.pendingReceipts?.delete(block.hash().toString('hex')) + this.pendingReceipts?.delete(bytesToHex(block.hash())) } } @@ -215,7 +215,7 @@ export class VMExecution extends Execution { continue } const blockByNumber = await this.chain.getBlock(block.header.number) - if (!blockByNumber.hash().equals(block.hash())) { + if (!equalsBytes(blockByNumber.hash(), block.hash())) { throw Error(`${blockName} not in canonical chain`) } } @@ -255,7 +255,7 @@ export class VMExecution extends Execution { ) let headBlock: Block | undefined - let parentState: Buffer | undefined + let parentState: Uint8Array | undefined let errorBlock: Block | undefined while ( @@ -265,7 +265,7 @@ export class VMExecution extends Execution { canonicalHead.header.number - startHeadBlock.header.number >= BigInt(this.config.numBlocksPerIteration))) && (numExecuted === undefined || (loop && numExecuted === this.config.numBlocksPerIteration)) && - startHeadBlock.hash().equals(canonicalHead.hash()) === false + equalsBytes(startHeadBlock.hash(), canonicalHead.hash()) === false ) { let txCounter = 0 headBlock = undefined @@ -274,10 +274,10 @@ export class VMExecution extends Execution { this.vmPromise = blockchain.iterator( 'vm', async (block: Block, reorg: boolean) => { - if (errorBlock) return + if (errorBlock !== undefined) return // determine starting state for block run // if we are just starting or if a chain reorg has happened - if (!headBlock || reorg) { + if (headBlock === undefined || reorg) { const headBlock = await blockchain.getBlock(block.header.parentHash) parentState = headBlock.header.stateRoot } @@ -326,7 +326,7 @@ export class VMExecution extends Execution { if (diffSec > this.MAX_TOLERATED_BLOCK_TIME) { const msg = `Slow block execution for block num=${ block.header.number - } hash=0x${block.hash().toString('hex')} txs=${block.transactions.length} gasUsed=${ + } hash=0x${bytesToHex(block.hash())} txs=${block.transactions.length} gasUsed=${ result.gasUsed } time=${diffSec}secs` this.config.logger.warn(msg) @@ -496,9 +496,9 @@ export class VMExecution extends Execution { const res = await vm.runBlock({ block, skipHeaderValidation: true }) const afterTS = Date.now() const diffSec = Math.round((afterTS - beforeTS) / 1000) - const msg = `Executed block num=${blockNumber} hash=0x${block.hash().toString('hex')} txs=${ - block.transactions.length - } gasUsed=${res.gasUsed} time=${diffSec}secs` + const msg = `Executed block num=${blockNumber} hash=${bytesToPrefixedHexString( + block.hash() + )} txs=${block.transactions.length} gasUsed=${res.gasUsed} time=${diffSec}secs` if (diffSec <= this.MAX_TOLERATED_BLOCK_TIME) { this.config.logger.info(msg) } else { @@ -510,7 +510,7 @@ export class VMExecution extends Execution { // Useful e.g. to trace slow txs const allTxs = txHashes.length === 1 && txHashes[0] === '*' ? true : false for (const tx of block.transactions) { - const txHash = bufferToHex(tx.hash()) + const txHash = bytesToHex(tx.hash()) if (allTxs || txHashes.includes(txHash)) { const res = await vm.runTx({ block, tx }) this.config.logger.info( diff --git a/packages/client/lib/miner/miner.ts b/packages/client/lib/miner/miner.ts index 24e87381e2..ad4ee93637 100644 --- a/packages/client/lib/miner/miner.ts +++ b/packages/client/lib/miner/miner.ts @@ -1,6 +1,8 @@ import { BlockHeader } from '@ethereumjs/block' import { ConsensusType, Hardfork } from '@ethereumjs/common' import { Ethash } from '@ethereumjs/ethash' +import { bytesToPrefixedHexString } from '@ethereumjs/util' +import { bytesToHex, equalsBytes } from 'ethereum-cryptography/utils' import { MemoryLevel } from 'memory-level' import { Event } from '../types' @@ -132,7 +134,7 @@ export class Miner { const header = this.latestBlockHeader() this.ethashMiner = this.ethash.getMiner(header) const solution = await this.ethashMiner.iterate(-1) - if (!header.hash().equals(this.latestBlockHeader().hash())) { + if (!equalsBytes(header.hash(), this.latestBlockHeader().hash())) { // New block was inserted while iterating so we will discard solution return } @@ -319,17 +321,17 @@ export class Miner { // We can here decide to keep a tx in pool if it belongs to future hf // but for simplicity just remove the tx as the sender can always retransmit // the tx - this.service.txPool.removeByHash(txs[index].hash().toString('hex')) + this.service.txPool.removeByHash(bytesToHex(txs[index].hash())) this.config.logger.error( - `Pending: Removed from txPool tx 0x${txs[index] - .hash() - .toString('hex')} having different hf=${txs[ - index - ].common.hardfork()} than block vm hf=${blockBuilder['vm']._common.hardfork()}` + `Pending: Removed from txPool tx ${bytesToPrefixedHexString( + txs[index].hash() + )} having different hf=${txs[index].common.hardfork()} than block vm hf=${blockBuilder[ + 'vm' + ]._common.hardfork()}` ) } else { // If there is an error adding a tx, it will be skipped - const hash = '0x' + txs[index].hash().toString('hex') + const hash = bytesToPrefixedHexString(txs[index].hash()) this.config.logger.debug( `Skipping tx ${hash}, error encountered when trying to add tx:\n${error}` ) diff --git a/packages/client/lib/miner/pendingBlock.ts b/packages/client/lib/miner/pendingBlock.ts index 542477f46e..802d354ec6 100644 --- a/packages/client/lib/miner/pendingBlock.ts +++ b/packages/client/lib/miner/pendingBlock.ts @@ -2,9 +2,12 @@ import { BlockHeader } from '@ethereumjs/block' import { BlobEIP4844Transaction } from '@ethereumjs/tx' import { TypeOutput, - bigIntToUnpaddedBuffer, - bufferToHex, - toBuffer, + bigIntToUnpaddedBytes, + bytesToHex, + bytesToPrefixedHexString, + concatBytes, + equalsBytes, + toBytes, toType, zeros, } from '@ethereumjs/util' @@ -32,8 +35,8 @@ interface PendingBlockOpts { interface BlobBundle { blockHash: string - blobs: Buffer[] - kzgCommitments: Buffer[] + blobs: Uint8Array[] + kzgCommitments: Uint8Array[] } /** * In the future this class should build a pending block by keeping the @@ -94,20 +97,20 @@ export class PendingBlock { // payload is uniquely defined by timestamp, parent and mixHash, gasLimit can also be // potentially included in the fcU in future and can be safely added in uniqueness calc - const timestampBuf = bigIntToUnpaddedBuffer(toType(timestamp ?? 0, TypeOutput.BigInt)) - const gasLimitBuf = bigIntToUnpaddedBuffer(gasLimit) - const mixHashBuf = toType(mixHash!, TypeOutput.Buffer) ?? zeros(32) - const payloadIdBuffer = toBuffer( - keccak256(Buffer.concat([parentBlock.hash(), mixHashBuf, timestampBuf, gasLimitBuf])).slice( + const timestampBuf = bigIntToUnpaddedBytes(toType(timestamp ?? 0, TypeOutput.BigInt)) + const gasLimitBuf = bigIntToUnpaddedBytes(gasLimit) + const mixHashBuf = toType(mixHash!, TypeOutput.Uint8Array) ?? zeros(32) + const payloadIdBytes = toBytes( + keccak256(concatBytes(parentBlock.hash(), mixHashBuf, timestampBuf, gasLimitBuf)).subarray( 0, 8 ) ) - const payloadId = bufferToHex(payloadIdBuffer) + const payloadId = bytesToPrefixedHexString(payloadIdBytes) // If payload has already been triggered, then return the payloadid if (this.pendingPayloads.get(payloadId)) { - return payloadIdBuffer + return payloadIdBytes } // Prune the builders and blobbundles @@ -176,9 +179,9 @@ export class PendingBlock { } else { // If there is an error adding a tx, it will be skipped this.config.logger.debug( - `Pending: Skipping tx 0x${txs[index] - .hash() - .toString('hex')}, error encountered when trying to add tx:\n${error}` + `Pending: Skipping tx ${bytesToPrefixedHexString( + txs[index].hash() + )}, error encountered when trying to add tx:\n${error}` ) } } @@ -202,15 +205,15 @@ export class PendingBlock { ) this.constructBlobsBundle(payloadId, blobTxs, header.hash()) } - return payloadIdBuffer + return payloadIdBytes } /** * Stops a pending payload */ - stop(payloadIdBuffer: Buffer | string) { + stop(payloadIdBytes: Uint8Array | string) { const payloadId = - typeof payloadIdBuffer !== 'string' ? bufferToHex(payloadIdBuffer) : payloadIdBuffer + typeof payloadIdBytes !== 'string' ? bytesToPrefixedHexString(payloadIdBytes) : payloadIdBytes const builder = this.pendingPayloads.get(payloadId) if (builder === undefined) return // Revert blockBuilder @@ -224,10 +227,10 @@ export class PendingBlock { * Returns the completed block */ async build( - payloadIdBuffer: Buffer | string + payloadIdBytes: Uint8Array | string ): Promise { const payloadId = - typeof payloadIdBuffer !== 'string' ? bufferToHex(payloadIdBuffer) : payloadIdBuffer + typeof payloadIdBytes !== 'string' ? bytesToPrefixedHexString(payloadIdBytes) : payloadIdBytes const builder = this.pendingPayloads.get(payloadId) if (!builder) { return @@ -241,8 +244,9 @@ export class PendingBlock { // Add new txs that the pool received const txs = (await this.txPool.txsByPriceAndNonce(vm, headerData.baseFeePerGas)).filter( (tx) => - (builder as any).transactions.some((t: TypedTransaction) => t.hash().equals(tx.hash())) === - false + (builder as any).transactions.some((t: TypedTransaction) => + equalsBytes(t.hash(), tx.hash()) + ) === false ) this.config.logger.info(`Pending: Adding ${txs.length} additional eligible txs`) let index = 0 @@ -269,11 +273,11 @@ export class PendingBlock { // We can here decide to keep a tx in pool if it belongs to future hf // but for simplicity just remove the tx as the sender can always retransmit // the tx - this.txPool.removeByHash(txs[index].hash().toString('hex')) + this.txPool.removeByHash(bytesToHex(txs[index].hash())) this.config.logger.error( - `Pending: Removed from txPool tx 0x${txs[index] - .hash() - .toString('hex')} having different hf=${txs[ + `Pending: Removed from txPool tx ${bytesToPrefixedHexString( + txs[index].hash() + )} having different hf=${txs[ index ].common.hardfork()} than block vm hf=${vm._common.hardfork()}` ) @@ -281,9 +285,9 @@ export class PendingBlock { skippedByAddErrors++ // If there is an error adding a tx, it will be skipped this.config.logger.debug( - `Pending: Skipping tx 0x${txs[index] - .hash() - .toString('hex')}, error encountered when trying to add tx:\n${error}` + `Pending: Skipping tx ${bytesToPrefixedHexString( + txs[index].hash() + )}, error encountered when trying to add tx:\n${error}` ) } } @@ -295,9 +299,7 @@ export class PendingBlock { this.config.logger.info( `Pending: Built block number=${block.header.number} txs=${ block.transactions.length - }${withdrawalsStr} skippedByAddErrors=${skippedByAddErrors} hash=${block - .hash() - .toString('hex')}` + }${withdrawalsStr} skippedByAddErrors=${skippedByAddErrors} hash=${bytesToHex(block.hash())}` ) // Construct blobs bundle @@ -317,10 +319,10 @@ export class PendingBlock { private constructBlobsBundle = ( payloadId: string, txs: BlobEIP4844Transaction[], - blockHash: Buffer + blockHash: Uint8Array ) => { - let blobs: Buffer[] = [] - let kzgCommitments: Buffer[] = [] + let blobs: Uint8Array[] = [] + let kzgCommitments: Uint8Array[] = [] const bundle = this.blobBundles.get(payloadId) if (bundle !== undefined) { blobs = bundle.blobs @@ -335,7 +337,7 @@ export class PendingBlock { } } this.blobBundles.set(payloadId, { - blockHash: '0x' + blockHash.toString('hex'), + blockHash: bytesToPrefixedHexString(blockHash), blobs, kzgCommitments, }) diff --git a/packages/client/lib/net/peer/rlpxpeer.ts b/packages/client/lib/net/peer/rlpxpeer.ts index b37f7d2407..014a30255a 100644 --- a/packages/client/lib/net/peer/rlpxpeer.ts +++ b/packages/client/lib/net/peer/rlpxpeer.ts @@ -4,7 +4,7 @@ import { RLPx as Devp2pRLPx, SNAP as Devp2pSNAP, } from '@ethereumjs/devp2p' -import { randomBytes } from 'crypto' +import { hexStringToBytes, randomBytes } from '@ethereumjs/util' import { Event } from '../../types' import { RlpxSender } from '../protocol' @@ -111,7 +111,7 @@ export class RlpxPeer extends Peer { common: this.config.chainCommon, }) await this.rlpx.connect({ - id: Buffer.from(this.id, 'hex'), + id: hexStringToBytes(this.id), address: this.host, tcpPort: this.port, }) diff --git a/packages/client/lib/net/protocol/ethprotocol.ts b/packages/client/lib/net/protocol/ethprotocol.ts index dc9b2463da..1a63af33d9 100644 --- a/packages/client/lib/net/protocol/ethprotocol.ts +++ b/packages/client/lib/net/protocol/ethprotocol.ts @@ -3,12 +3,10 @@ import { Hardfork } from '@ethereumjs/common' import { RLP } from '@ethereumjs/rlp' import { BlobEIP4844Transaction, TransactionFactory } from '@ethereumjs/tx' import { - arrToBufArr, - bigIntToUnpaddedBuffer, - bufArrToArr, - bufferToBigInt, - bufferToInt, - intToUnpaddedBuffer, + bigIntToUnpaddedBytes, + bytesToBigInt, + bytesToInt, + intToUnpaddedBytes, } from '@ethereumjs/util' import { encodeReceipt } from '@ethereumjs/vm/dist/runBlock' @@ -17,9 +15,10 @@ import { Protocol } from './protocol' import type { Chain } from '../../blockchain' import type { TxReceiptWithType } from '../../execution/receipt' import type { Message, ProtocolOptions } from './protocol' -import type { BlockBodyBuffer, BlockBuffer, BlockHeaderBuffer } from '@ethereumjs/block' +import type { BlockBodyBytes, BlockBytes, BlockHeaderBytes } from '@ethereumjs/block' +import type { Log } from '@ethereumjs/evm' import type { TypedTransaction } from '@ethereumjs/tx' -import type { BigIntLike } from '@ethereumjs/util' +import type { BigIntLike, NestedUint8Array } from '@ethereumjs/util' import type { PostByzantiumTxReceipt, PreByzantiumTxReceipt, TxReceipt } from '@ethereumjs/vm' interface EthProtocolOptions extends ProtocolOptions { @@ -31,7 +30,7 @@ type GetBlockHeadersOpts = { /* Request id (default: next internal id) */ reqId?: bigint /* The block's number or hash */ - block: bigint | Buffer + block: bigint | Uint8Array /* Max number of blocks to return */ max: number /* Number of blocks to skip apart (default: 0) */ @@ -44,21 +43,21 @@ type GetBlockBodiesOpts = { /* Request id (default: next internal id) */ reqId?: bigint /* The block hashes */ - hashes: Buffer[] + hashes: Uint8Array[] } type GetPooledTransactionsOpts = { /* Request id (default: next internal id) */ reqId?: bigint /* The tx hashes */ - hashes: Buffer[] + hashes: Uint8Array[] } type GetReceiptsOpts = { /* Request id (default: next internal id) */ reqId?: bigint /* The block hashes to request receipts for */ - hashes: Buffer[] + hashes: Uint8Array[] } /* @@ -67,7 +66,7 @@ type GetReceiptsOpts = { */ export interface EthProtocolMethods { getBlockHeaders: (opts: GetBlockHeadersOpts) => Promise<[bigint, BlockHeader[]]> - getBlockBodies: (opts: GetBlockBodiesOpts) => Promise<[bigint, BlockBodyBuffer[]]> + getBlockBodies: (opts: GetBlockBodiesOpts) => Promise<[bigint, BlockBodyBytes[]]> getPooledTransactions: (opts: GetPooledTransactionsOpts) => Promise<[bigint, TypedTransaction[]]> getReceipts: (opts: GetReceiptsOpts) => Promise<[bigint, TxReceipt[]]> } @@ -86,8 +85,8 @@ export class EthProtocol extends Protocol { { name: 'NewBlockHashes', code: 0x01, - encode: (hashes: any[]) => hashes.map((hn) => [hn[0], bigIntToUnpaddedBuffer(hn[1])]), - decode: (hashes: any[]) => hashes.map((hn) => [hn[0], bufferToBigInt(hn[1])]), + encode: (hashes: any[]) => hashes.map((hn) => [hn[0], bigIntToUnpaddedBytes(hn[1])]), + decode: (hashes: any[]) => hashes.map((hn) => [hn[0], bytesToBigInt(hn[1])]), }, { name: 'Transactions', @@ -101,7 +100,7 @@ export class EthProtocol extends Protocol { } return serializedTxs }, - decode: (txs: Buffer[]) => { + decode: (txs: Uint8Array[]) => { if (!this.config.synchronized) return const common = this.config.chainCommon.copy() common.setHardforkByBlockNumber( @@ -120,31 +119,31 @@ export class EthProtocol extends Protocol { code: 0x03, response: 0x04, encode: ({ reqId, block, max, skip = 0, reverse = false }: GetBlockHeadersOpts) => [ - bigIntToUnpaddedBuffer(reqId ?? ++this.nextReqId), + bigIntToUnpaddedBytes(reqId ?? ++this.nextReqId), [ - typeof block === 'bigint' ? bigIntToUnpaddedBuffer(block) : block, - intToUnpaddedBuffer(max), - intToUnpaddedBuffer(skip), - intToUnpaddedBuffer(!reverse ? 0 : 1), + typeof block === 'bigint' ? bigIntToUnpaddedBytes(block) : block, + intToUnpaddedBytes(max), + intToUnpaddedBytes(skip), + intToUnpaddedBytes(!reverse ? 0 : 1), ], ], decode: ([reqId, [block, max, skip, reverse]]: any) => ({ - reqId: bufferToBigInt(reqId), - block: block.length === 32 ? block : bufferToBigInt(block), - max: bufferToInt(max), - skip: bufferToInt(skip), - reverse: bufferToInt(reverse) === 0 ? false : true, + reqId: bytesToBigInt(reqId), + block: block.length === 32 ? block : bytesToBigInt(block), + max: bytesToInt(max), + skip: bytesToInt(skip), + reverse: bytesToInt(reverse) === 0 ? false : true, }), }, { name: 'BlockHeaders', code: 0x04, encode: ({ reqId, headers }: { reqId: bigint; headers: BlockHeader[] }) => [ - bigIntToUnpaddedBuffer(reqId), + bigIntToUnpaddedBytes(reqId), headers.map((h) => h.raw()), ], - decode: ([reqId, headers]: [Buffer, BlockHeaderBuffer[]]) => [ - bufferToBigInt(reqId), + decode: ([reqId, headers]: [Uint8Array, BlockHeaderBytes[]]) => [ + bytesToBigInt(reqId), headers.map((h) => { const headerData = valuesArrayToHeaderData(h) const difficulty = getDifficulty(headerData)! @@ -166,28 +165,28 @@ export class EthProtocol extends Protocol { code: 0x05, response: 0x06, encode: ({ reqId, hashes }: GetBlockBodiesOpts) => [ - bigIntToUnpaddedBuffer(reqId ?? ++this.nextReqId), + bigIntToUnpaddedBytes(reqId ?? ++this.nextReqId), hashes, ], - decode: ([reqId, hashes]: [Buffer, Buffer[]]) => ({ - reqId: bufferToBigInt(reqId), + decode: ([reqId, hashes]: [Uint8Array, Uint8Array[]]) => ({ + reqId: bytesToBigInt(reqId), hashes, }), }, { name: 'BlockBodies', code: 0x06, - encode: ({ reqId, bodies }: { reqId: bigint; bodies: BlockBodyBuffer[] }) => [ - bigIntToUnpaddedBuffer(reqId), + encode: ({ reqId, bodies }: { reqId: bigint; bodies: BlockBodyBytes[] }) => [ + bigIntToUnpaddedBytes(reqId), bodies, ], - decode: ([reqId, bodies]: [Buffer, BlockBodyBuffer[]]) => [bufferToBigInt(reqId), bodies], + decode: ([reqId, bodies]: [Uint8Array, BlockBodyBytes[]]) => [bytesToBigInt(reqId), bodies], }, { name: 'NewBlock', code: 0x07, - encode: ([block, td]: [Block, bigint]) => [block.raw(), bigIntToUnpaddedBuffer(td)], - decode: ([block, td]: [BlockBuffer, Buffer]) => [ + encode: ([block, td]: [Block, bigint]) => [block.raw(), bigIntToUnpaddedBytes(td)], + decode: ([block, td]: [BlockBytes, Uint8Array]) => [ Block.fromValuesArray(block, { common: this.config.chainCommon, hardforkByBlockNumber: true, @@ -198,19 +197,19 @@ export class EthProtocol extends Protocol { { name: 'NewPooledTransactionHashes', code: 0x08, - encode: (hashes: Buffer[]) => hashes, - decode: (hashes: Buffer[]) => hashes, + encode: (hashes: Uint8Array[]) => hashes, + decode: (hashes: Uint8Array[]) => hashes, }, { name: 'GetPooledTransactions', code: 0x09, response: 0x0a, encode: ({ reqId, hashes }: GetPooledTransactionsOpts) => [ - bigIntToUnpaddedBuffer(reqId ?? ++this.nextReqId), + bigIntToUnpaddedBytes(reqId ?? ++this.nextReqId), hashes, ], - decode: ([reqId, hashes]: [Buffer, Buffer[]]) => ({ - reqId: bufferToBigInt(reqId), + decode: ([reqId, hashes]: [Uint8Array, Uint8Array[]]) => ({ + reqId: bytesToBigInt(reqId), hashes, }), }, @@ -232,9 +231,9 @@ export class EthProtocol extends Protocol { break } } - return [bigIntToUnpaddedBuffer(reqId), serializedTxs] + return [bigIntToUnpaddedBytes(reqId), serializedTxs] }, - decode: ([reqId, txs]: [Buffer, any[]]) => { + decode: ([reqId, txs]: [Uint8Array, any[]]) => { const common = this.config.chainCommon.copy() common.setHardforkByBlockNumber( this.chain.headers.latest?.number ?? // Use latest header number if available OR @@ -245,7 +244,7 @@ export class EthProtocol extends Protocol { this.chain.headers.latest?.timestamp ?? Math.floor(Date.now() / 1000) ) return [ - bufferToBigInt(reqId), + bytesToBigInt(reqId), txs.map((txData) => { if (txData[0] === 5) { // Blob transactions are deserialized with network wrapper @@ -260,12 +259,12 @@ export class EthProtocol extends Protocol { name: 'GetReceipts', code: 0x0f, response: 0x10, - encode: ({ reqId, hashes }: { reqId: bigint; hashes: Buffer[] }) => [ - bigIntToUnpaddedBuffer(reqId ?? ++this.nextReqId), + encode: ({ reqId, hashes }: { reqId: bigint; hashes: Uint8Array[] }) => [ + bigIntToUnpaddedBytes(reqId ?? ++this.nextReqId), hashes, ], - decode: ([reqId, hashes]: [Buffer, Buffer[]]) => ({ - reqId: bufferToBigInt(reqId), + decode: ([reqId, hashes]: [Uint8Array, Uint8Array[]]) => ({ + reqId: bytesToBigInt(reqId), hashes, }), }, @@ -278,23 +277,28 @@ export class EthProtocol extends Protocol { const encodedReceipt = encodeReceipt(receipt, receipt.txType) serializedReceipts.push(encodedReceipt) } - return [bigIntToUnpaddedBuffer(reqId), serializedReceipts] + return [bigIntToUnpaddedBytes(reqId), serializedReceipts] }, - decode: ([reqId, receipts]: [Buffer, Buffer[]]) => [ - bufferToBigInt(reqId), + decode: ([reqId, receipts]: [Uint8Array, Uint8Array[]]) => [ + bytesToBigInt(reqId), receipts.map((r) => { // Legacy receipt if r[0] >= 0xc0, otherwise typed receipt with first byte as TransactionType - const decoded = arrToBufArr(RLP.decode(bufArrToArr(r[0] >= 0xc0 ? r : r.slice(1)))) as any - const [stateRootOrStatus, cumulativeGasUsed, logsBloom, logs] = decoded + const decoded = RLP.decode(r[0] >= 0xc0 ? r : r.subarray(1)) as NestedUint8Array + const [stateRootOrStatus, cumulativeGasUsed, logsBloom, logs] = decoded as [ + Uint8Array, + Uint8Array, + Uint8Array, + Log[] + ] const receipt = { - cumulativeBlockGasUsed: bufferToBigInt(cumulativeGasUsed), + cumulativeBlockGasUsed: bytesToBigInt(cumulativeGasUsed), bitvector: logsBloom, logs, } as TxReceipt if (stateRootOrStatus.length === 32) { ;(receipt as PreByzantiumTxReceipt).stateRoot = stateRootOrStatus } else { - ;(receipt as PostByzantiumTxReceipt).status = bufferToInt(stateRootOrStatus) as 0 | 1 + ;(receipt as PostByzantiumTxReceipt).status = bytesToInt(stateRootOrStatus) as 0 | 1 } return receipt }), @@ -352,11 +356,11 @@ export class EthProtocol extends Protocol { */ encodeStatus(): any { return { - networkId: bigIntToUnpaddedBuffer(this.chain.networkId), - td: bigIntToUnpaddedBuffer(this.chain.blocks.td), + networkId: bigIntToUnpaddedBytes(this.chain.networkId), + td: bigIntToUnpaddedBytes(this.chain.blocks.td), bestHash: this.chain.blocks.latest!.hash(), genesisHash: this.chain.genesis.hash(), - latestBlock: bigIntToUnpaddedBuffer(this.chain.blocks.latest!.header.number), + latestBlock: bigIntToUnpaddedBytes(this.chain.blocks.latest!.header.number), } } @@ -366,8 +370,8 @@ export class EthProtocol extends Protocol { */ decodeStatus(status: any): any { return { - networkId: bufferToBigInt(status.networkId), - td: bufferToBigInt(status.td), + networkId: bytesToBigInt(status.networkId), + td: bytesToBigInt(status.td), bestHash: status.bestHash, genesisHash: status.genesisHash, } diff --git a/packages/client/lib/net/protocol/lesprotocol.ts b/packages/client/lib/net/protocol/lesprotocol.ts index 50acc2de53..62e3eb27c7 100644 --- a/packages/client/lib/net/protocol/lesprotocol.ts +++ b/packages/client/lib/net/protocol/lesprotocol.ts @@ -1,12 +1,18 @@ import { BlockHeader } from '@ethereumjs/block' -import { bigIntToUnpaddedBuffer, bufferToBigInt, bufferToInt, intToBuffer } from '@ethereumjs/util' +import { + bigIntToUnpaddedBytes, + bytesToBigInt, + bytesToInt, + hexStringToBytes, + intToBytes, +} from '@ethereumjs/util' import { Protocol } from './protocol' import type { Chain } from '../../blockchain' import type { FlowControl } from './flowcontrol' import type { Message, ProtocolOptions } from './protocol' -import type { BlockHeaderBuffer } from '@ethereumjs/block' +import type { BlockHeaderBytes } from '@ethereumjs/block' export interface LesProtocolOptions extends ProtocolOptions { /* Blockchain */ @@ -20,7 +26,7 @@ type GetBlockHeadersOpts = { /* Request id (default: next internal id) */ reqId?: bigint /* The block's number or hash */ - block: bigint | Buffer + block: bigint | Uint8Array /* Max number of blocks to return */ max: number /* Number of blocks to skip apart (default: 0) */ @@ -56,16 +62,16 @@ export class LesProtocol extends Protocol { encode: ({ headHash, headNumber, headTd, reorgDepth }: any) => [ // TO DO: handle state changes headHash, - bigIntToUnpaddedBuffer(headNumber), - bigIntToUnpaddedBuffer(headTd), - intToBuffer(reorgDepth), + bigIntToUnpaddedBytes(headNumber), + bigIntToUnpaddedBytes(headTd), + intToBytes(reorgDepth), ], decode: ([headHash, headNumber, headTd, reorgDepth]: any) => ({ // TO DO: handle state changes headHash, - headNumber: bufferToBigInt(headNumber), - headTd: bufferToBigInt(headTd), - reorgDepth: bufferToInt(reorgDepth), + headNumber: bytesToBigInt(headNumber), + headTd: bytesToBigInt(headTd), + reorgDepth: bytesToInt(reorgDepth), }), }, { @@ -73,34 +79,35 @@ export class LesProtocol extends Protocol { code: 0x02, response: 0x03, encode: ({ reqId, block, max, skip = 0, reverse = false }: GetBlockHeadersOpts) => [ - bigIntToUnpaddedBuffer(reqId ?? ++this.nextReqId), + bigIntToUnpaddedBytes(reqId ?? ++this.nextReqId), [ - typeof block === 'bigint' ? bigIntToUnpaddedBuffer(block) : block, - max, - skip, - !reverse ? 0 : 1, + typeof block === 'bigint' ? bigIntToUnpaddedBytes(block) : block, + intToBytes(max), + intToBytes(skip), + intToBytes(!reverse ? 0 : 1), ], ], decode: ([reqId, [block, max, skip, reverse]]: any) => ({ - reqId: bufferToBigInt(reqId), - block: block.length === 32 ? block : bufferToBigInt(block), - max: bufferToInt(max), - skip: bufferToInt(skip), - reverse: bufferToInt(reverse) === 0 ? false : true, + reqId: bytesToBigInt(reqId), + block: block.length === 32 ? block : bytesToBigInt(block), + max: bytesToInt(max), + skip: bytesToInt(skip), + reverse: bytesToInt(reverse) === 0 ? false : true, }), }, + { name: 'BlockHeaders', code: 0x03, encode: ({ reqId, bv, headers }: any) => [ - bigIntToUnpaddedBuffer(reqId), - bigIntToUnpaddedBuffer(bv), + bigIntToUnpaddedBytes(reqId), + bigIntToUnpaddedBytes(bv), headers.map((h: BlockHeader) => h.raw()), ], decode: ([reqId, bv, headers]: any) => ({ - reqId: bufferToBigInt(reqId), - bv: bufferToBigInt(bv), - headers: headers.map((h: BlockHeaderBuffer) => + reqId: bytesToBigInt(reqId), + bv: bytesToBigInt(bv), + headers: headers.map((h: BlockHeaderBytes) => BlockHeader.fromValuesArray(h, { hardforkByBlockNumber: true, common: this.config.chainCommon, // eslint-disable-line no-invalid-this @@ -167,11 +174,11 @@ export class LesProtocol extends Protocol { serveChainSince: 0, serveStateSince: 0, // txRelay: 1, TODO: uncomment with client tx pool functionality - 'flowControl/BL': intToBuffer(this.flow.bl), - 'flowControl/MRR': intToBuffer(this.flow.mrr), + 'flowControl/BL': intToBytes(this.flow.bl), + 'flowControl/MRR': intToBytes(this.flow.mrr), 'flowControl/MRC': Object.entries(this.flow.mrc).map(([name, { base, req }]) => { const { code } = this.messages.find((m) => m.name === name)! - return [intToBuffer(code), intToBuffer(base), intToBuffer(req)] + return [intToBytes(code), intToBytes(base), intToBytes(req)] }), } } @@ -183,16 +190,16 @@ export class LesProtocol extends Protocol { const nextFork = this.config.chainCommon.nextHardforkBlockOrTimestamp( this.config.chainCommon.hardfork() ) - const forkID = [Buffer.from(forkHash.slice(2), 'hex'), bigIntToUnpaddedBuffer(nextFork ?? 0n)] + const forkID = [hexStringToBytes(forkHash.slice(2)), bigIntToUnpaddedBytes(nextFork ?? 0n)] return { - networkId: bigIntToUnpaddedBuffer(this.chain.networkId), - headTd: bigIntToUnpaddedBuffer(this.chain.headers.td), + networkId: bigIntToUnpaddedBytes(this.chain.networkId), + headTd: bigIntToUnpaddedBytes(this.chain.headers.td), headHash: this.chain.headers.latest?.hash(), - headNum: bigIntToUnpaddedBuffer(this.chain.headers.height), + headNum: bigIntToUnpaddedBytes(this.chain.headers.height), genesisHash: this.chain.genesis.hash(), forkID, - recentTxLookup: intToBuffer(1), + recentTxLookup: intToBytes(1), ...serveOptions, } } @@ -206,7 +213,7 @@ export class LesProtocol extends Protocol { const mrc: any = {} if (status['flowControl/MRC'] !== undefined) { for (let entry of status['flowControl/MRC']) { - entry = entry.map((e: any) => bufferToInt(e)) + entry = entry.map((e: any) => bytesToInt(e)) mrc[entry[0]] = { base: entry[1], req: entry[2] } const message = this.messages.find((m) => m.code === entry[0]) if (message) { @@ -215,10 +222,10 @@ export class LesProtocol extends Protocol { } } return { - networkId: bufferToBigInt(status.networkId), - headTd: bufferToBigInt(status.headTd), + networkId: bytesToBigInt(status.networkId), + headTd: bytesToBigInt(status.headTd), headHash: status.headHash, - headNum: bufferToBigInt(status.headNum), + headNum: bytesToBigInt(status.headNum), genesisHash: status.genesisHash, forkID: status.forkID, recentTxLookup: status.recentTxLookup, @@ -226,12 +233,9 @@ export class LesProtocol extends Protocol { serveChainSince: status.serveChainSince ?? 0, serveStateSince: status.serveStateSince ?? 0, txRelay: status.txRelay === true, - bl: - status['flowControl/BL'] !== undefined ? bufferToInt(status['flowControl/BL']) : undefined, + bl: status['flowControl/BL'] !== undefined ? bytesToInt(status['flowControl/BL']) : undefined, mrr: - status['flowControl/MRR'] !== undefined - ? bufferToInt(status['flowControl/MRR']) - : undefined, + status['flowControl/MRR'] !== undefined ? bytesToInt(status['flowControl/MRR']) : undefined, mrc, } } diff --git a/packages/client/lib/net/protocol/libp2psender.ts b/packages/client/lib/net/protocol/libp2psender.ts index 5df71836a5..b1da0b9753 100644 --- a/packages/client/lib/net/protocol/libp2psender.ts +++ b/packages/client/lib/net/protocol/libp2psender.ts @@ -1,15 +1,16 @@ import { RLP } from '@ethereumjs/rlp' -import { arrToBufArr, bufArrToArr, bufferToInt, intToBuffer } from '@ethereumjs/util' +import { bytesToInt, bytesToUtf8, intToBytes, utf8ToBytes } from '@ethereumjs/util' import * as pipe from 'it-pipe' import * as pushable from 'it-pushable' import { Sender } from './sender' import type { Libp2pMuxedStream as MuxedStream } from '../../types' +import type { NestedUint8Array } from '@ethereumjs/util' // TypeScript doesn't have support yet for ReturnType // with generic types, so this wrapper is used as a helper. -const wrapperPushable = () => pushable() +const wrapperPushable = () => pushable() type Pushable = ReturnType /** @@ -41,15 +42,15 @@ export class Libp2pSender extends Sender { // incoming stream void pipe.pipe(this.stream, async (source: any) => { for await (const bl of source) { - // convert BufferList to Buffer - const data: Buffer = bl.slice() + // convert BytesList to Uint8Array + const data: Uint8Array = bl.slice() try { - const [codeBuf, payload]: any = arrToBufArr(RLP.decode(Uint8Array.from(data))) - const code = bufferToInt(codeBuf) + const [codeBuf, payload] = RLP.decode(Uint8Array.from(data)) + const code = bytesToInt(codeBuf as Uint8Array) if (code === 0) { const status: any = {} - for (const [k, v] of payload.values()) { - status[k.toString()] = v + for (const [k, v] of (payload as NestedUint8Array).values()) { + status[bytesToUtf8(k as Uint8Array)] = v } this.status = status } else { @@ -67,8 +68,8 @@ export class Libp2pSender extends Sender { * @param status */ sendStatus(status: any) { - const payload: any = Object.entries(status).map(([k, v]) => [Buffer.from(k), v]) - this.pushable.push(Buffer.from(RLP.encode(bufArrToArr([intToBuffer(0), payload])))) + const payload: any = Object.entries(status).map(([k, v]) => [utf8ToBytes(k), v]) + this.pushable.push(RLP.encode([intToBytes(0), payload])) } /** @@ -77,6 +78,6 @@ export class Libp2pSender extends Sender { * @param data message payload */ sendMessage(code: number, data: any) { - this.pushable.push(Buffer.from(RLP.encode(bufArrToArr([intToBuffer(code), data])))) + this.pushable.push(RLP.encode([intToBytes(code), data])) } } diff --git a/packages/client/lib/net/protocol/sender.ts b/packages/client/lib/net/protocol/sender.ts index 2f8d8b8641..6a172f31e0 100644 --- a/packages/client/lib/net/protocol/sender.ts +++ b/packages/client/lib/net/protocol/sender.ts @@ -38,7 +38,7 @@ export class Sender extends EventEmitter { * @param code message code * @param rlpEncodedData rlp encoded message payload */ - sendMessage(_code: number, _rlpEncodedData: any[] | Buffer) { + sendMessage(_code: number, _rlpEncodedData: any[] | Uint8Array) { throw new Error('Unimplemented') } } diff --git a/packages/client/lib/net/protocol/snapprotocol.ts b/packages/client/lib/net/protocol/snapprotocol.ts index ae604af26a..6dc738d56c 100644 --- a/packages/client/lib/net/protocol/snapprotocol.ts +++ b/packages/client/lib/net/protocol/snapprotocol.ts @@ -1,8 +1,8 @@ import { accountBodyFromSlim, accountBodyToSlim, - bigIntToUnpaddedBuffer, - bufferToBigInt, + bigIntToUnpaddedBytes, + bytesToBigInt, setLengthLeft, } from '@ethereumjs/util' @@ -10,7 +10,7 @@ import { Protocol } from './protocol' import type { Chain } from '../../blockchain' import type { Message, ProtocolOptions } from './protocol' -import type { AccountBodyBuffer } from '@ethereumjs/util' +import type { AccountBodyBytes } from '@ethereumjs/util' interface SnapProtocolOptions extends ProtocolOptions { /* Blockchain */ @@ -23,22 +23,22 @@ interface SnapProtocolOptions extends ProtocolOptions { } export type AccountData = { - hash: Buffer - body: AccountBodyBuffer + hash: Uint8Array + body: AccountBodyBytes } type GetAccountRangeOpts = { /* Request id (default: next internal id) */ reqId?: bigint - root: Buffer - origin: Buffer - limit: Buffer + root: Uint8Array + origin: Uint8Array + limit: Uint8Array bytes: bigint } type GetStorageRangesOpts = { reqId?: bigint - root: Buffer + root: Uint8Array // If multiple accounts' storage is requested, serving nodes // should reply with the entire storage ranges (thus no Merkle @@ -51,27 +51,27 @@ type GetStorageRangesOpts = { // starting hash, up to the last one or until the packet fills // up. It the entire storage range is not being returned, a // Merkle proof must be attached. - accounts: Buffer[] - origin: Buffer - limit: Buffer + accounts: Uint8Array[] + origin: Uint8Array + limit: Uint8Array bytes: bigint } export type StorageData = { - hash: Buffer - body: Buffer + hash: Uint8Array + body: Uint8Array } type GetByteCodesOpts = { reqId?: bigint - hashes: Buffer[] + hashes: Uint8Array[] bytes: bigint } type GetTrieNodesOpts = { reqId?: bigint - root: Buffer - paths: Buffer[][] + root: Uint8Array + paths: Uint8Array[][] bytes: bigint } /* @@ -81,11 +81,11 @@ type GetTrieNodesOpts = { export interface SnapProtocolMethods { getAccountRange: ( opts: GetAccountRangeOpts - ) => Promise<{ reqId: bigint; accounts: AccountData[]; proof: Buffer[] }> + ) => Promise<{ reqId: bigint; accounts: AccountData[]; proof: Uint8Array[] }> getStorageRanges: (opts: GetStorageRangesOpts) => Promise<{ reqId: bigint slots: StorageData[][] - proof: Buffer[] + proof: Uint8Array[] }> getByteCodes: (opts: GetByteCodesOpts) => Promise<{ reqId: bigint; codes: Buffer[] }> getTrieNodes: (opts: GetTrieNodesOpts) => Promise<{ reqId: bigint; nodes: Buffer[] }> @@ -110,20 +110,20 @@ export class SnapProtocol extends Protocol { // [reqID: P, rootHash: B_32, startingHash: B_32, limitHash: B_32, responseBytes: P] encode: ({ reqId, root, origin, limit, bytes }: GetAccountRangeOpts) => { return [ - bigIntToUnpaddedBuffer(reqId ?? ++this.nextReqId), + bigIntToUnpaddedBytes(reqId ?? ++this.nextReqId), setLengthLeft(root, 32), setLengthLeft(origin, 32), setLengthLeft(limit, 32), - bigIntToUnpaddedBuffer(bytes), + bigIntToUnpaddedBytes(bytes), ] }, decode: ([reqId, root, origin, limit, bytes]: any) => { return { - reqId: bufferToBigInt(reqId), + reqId: bytesToBigInt(reqId), root, origin, limit, - bytes: bufferToBigInt(bytes), + bytes: bytesToBigInt(bytes), } }, }, @@ -138,10 +138,10 @@ export class SnapProtocol extends Protocol { }: { reqId: bigint accounts: AccountData[] - proof: Buffer[] + proof: Uint8Array[] }) => { return [ - bigIntToUnpaddedBuffer(reqId ?? ++this.nextReqId), + bigIntToUnpaddedBytes(reqId ?? ++this.nextReqId), accounts.map((account) => [ setLengthLeft(account.hash, 32), accountBodyToSlim(account.body), @@ -151,7 +151,7 @@ export class SnapProtocol extends Protocol { }, decode: ([reqId, accounts, proof]: any) => { return { - reqId: bufferToBigInt(reqId), + reqId: bytesToBigInt(reqId), accounts: accounts.map( ([hash, body]: any) => ({ @@ -170,22 +170,22 @@ export class SnapProtocol extends Protocol { // [reqID: P, rootHash: B_32, accountHashes: [B_32], startingHash: B, limitHash: B, responseBytes: P] encode: ({ reqId, root, accounts, origin, limit, bytes }: GetStorageRangesOpts) => { return [ - bigIntToUnpaddedBuffer(reqId ?? ++this.nextReqId), + bigIntToUnpaddedBytes(reqId ?? ++this.nextReqId), setLengthLeft(root, 32), accounts.map((acc) => setLengthLeft(acc, 32)), origin, limit, - bigIntToUnpaddedBuffer(bytes), + bigIntToUnpaddedBytes(bytes), ] }, decode: ([reqId, root, accounts, origin, limit, bytes]: any) => { return { - reqId: bufferToBigInt(reqId), + reqId: bytesToBigInt(reqId), root, accounts, origin, limit, - bytes: bufferToBigInt(bytes), + bytes: bytesToBigInt(bytes), } }, }, @@ -200,10 +200,10 @@ export class SnapProtocol extends Protocol { }: { reqId: bigint slots: StorageData[][] - proof: Buffer[] + proof: Uint8Array[] }) => { return [ - bigIntToUnpaddedBuffer(reqId ?? ++this.nextReqId), + bigIntToUnpaddedBytes(reqId ?? ++this.nextReqId), slots.map((accSlots) => accSlots.map((slotData) => [setLengthLeft(slotData.hash, 32), slotData.body]) ), @@ -212,7 +212,7 @@ export class SnapProtocol extends Protocol { }, decode: ([reqId, slots, proof]: any) => { return { - reqId: bufferToBigInt(reqId), + reqId: bytesToBigInt(reqId), slots: slots.map((accSlots: any) => accSlots.map(([hash, body]: any) => ({ hash, body } as StorageData)) ), @@ -227,16 +227,16 @@ export class SnapProtocol extends Protocol { // [reqID: P, hashes: [hash1: B_32, hash2: B_32, ...], bytes: P] encode: ({ reqId, hashes, bytes }: GetByteCodesOpts) => { return [ - bigIntToUnpaddedBuffer(reqId ?? ++this.nextReqId), + bigIntToUnpaddedBytes(reqId ?? ++this.nextReqId), hashes.map((hash) => setLengthLeft(hash, 32)), - bigIntToUnpaddedBuffer(bytes), + bigIntToUnpaddedBytes(bytes), ] }, decode: ([reqId, hashes, bytes]: any) => { return { - reqId: bufferToBigInt(reqId), + reqId: bytesToBigInt(reqId), hashes, - bytes: bufferToBigInt(bytes), + bytes: bytesToBigInt(bytes), } }, }, @@ -244,12 +244,12 @@ export class SnapProtocol extends Protocol { name: 'ByteCodes', code: 0x05, // [reqID: P, codes: [code1: B, code2: B, ...]] - encode: ({ reqId, codes }: { reqId: bigint; codes: Buffer[] }) => { - return [bigIntToUnpaddedBuffer(reqId ?? ++this.nextReqId), codes] + encode: ({ reqId, codes }: { reqId: bigint; codes: Uint8Array[] }) => { + return [bigIntToUnpaddedBytes(reqId ?? ++this.nextReqId), codes] }, decode: ([reqId, codes]: any) => { return { - reqId: bufferToBigInt(reqId), + reqId: bytesToBigInt(reqId), codes, } }, @@ -261,18 +261,18 @@ export class SnapProtocol extends Protocol { // [reqID: P, rootHash: B_32, paths: [[accPath: B, slotPath1: B, slotPath2: B, ...]...], bytes: P] encode: ({ reqId, root, paths, bytes }: GetTrieNodesOpts) => { return [ - bigIntToUnpaddedBuffer(reqId ?? ++this.nextReqId), + bigIntToUnpaddedBytes(reqId ?? ++this.nextReqId), setLengthLeft(root, 32), paths, - bigIntToUnpaddedBuffer(bytes), + bigIntToUnpaddedBytes(bytes), ] }, decode: ([reqId, root, paths, bytes]: any) => { return { - reqId: bufferToBigInt(reqId), + reqId: bytesToBigInt(reqId), root, paths, - bytes: bufferToBigInt(bytes), + bytes: bytesToBigInt(bytes), } }, }, @@ -280,12 +280,12 @@ export class SnapProtocol extends Protocol { name: 'TrieNodes', code: 0x07, // [reqID: P, nodes: [node1: B, node2: B, ...]] - encode: ({ reqId, nodes }: { reqId: bigint; nodes: Buffer[] }) => { - return [bigIntToUnpaddedBuffer(reqId ?? ++this.nextReqId), nodes] + encode: ({ reqId, nodes }: { reqId: bigint; nodes: Uint8Array[] }) => { + return [bigIntToUnpaddedBytes(reqId ?? ++this.nextReqId), nodes] }, decode: ([reqId, nodes]: any) => { return { - reqId: bufferToBigInt(reqId), + reqId: bytesToBigInt(reqId), nodes, } }, diff --git a/packages/client/lib/net/server/rlpxserver.ts b/packages/client/lib/net/server/rlpxserver.ts index 89e813317a..9d5f90eb6f 100644 --- a/packages/client/lib/net/server/rlpxserver.ts +++ b/packages/client/lib/net/server/rlpxserver.ts @@ -1,4 +1,5 @@ import { DPT as Devp2pDPT, RLPx as Devp2pRLPx } from '@ethereumjs/devp2p' +import { bytesToHex, utf8ToBytes } from 'ethereum-cryptography/utils' import { Event } from '../../types' import { getClientVersion } from '../../util' @@ -28,8 +29,8 @@ const ignoredErrors = new RegExp( // DPT message decoding 'Hash verification failed', - 'Invalid address buffer', - 'Invalid timestamp buffer', + 'Invalid address bytes', + 'Invalid timestamp bytes', 'Invalid type', 'Timeout error: ping', // connection 'Peer is banned', // connection @@ -104,7 +105,7 @@ export class RlpxServer extends Server { ports: { discovery: this.config.port, listener: this.config.port }, } } - const id = this.rlpx._id.toString('hex') + const id = bytesToHex(this.rlpx._id) return { enode: `enode://${id}@${listenAddr}`, id, @@ -239,7 +240,7 @@ export class RlpxServer extends Server { private async initRlpx() { return new Promise((resolve) => { this.rlpx = new Devp2pRLPx(this.key, { - clientId: Buffer.from(getClientVersion()), + clientId: utf8ToBytes(getClientVersion()), dpt: this.dpt!, maxPeers: this.config.maxPeers, capabilities: RlpxPeer.capabilities(Array.from(this.protocols)), @@ -251,7 +252,7 @@ export class RlpxServer extends Server { this.rlpx.on('peer:added', async (rlpxPeer: Devp2pRLPxPeer) => { const peer = new RlpxPeer({ config: this.config, - id: rlpxPeer.getId()!.toString('hex'), + id: bytesToHex(rlpxPeer.getId()!), host: rlpxPeer._socket.remoteAddress!, port: rlpxPeer._socket.remotePort!, protocols: Array.from(this.protocols), @@ -270,7 +271,7 @@ export class RlpxServer extends Server { }) this.rlpx.on('peer:removed', (rlpxPeer: Devp2pRLPxPeer, reason: any) => { - const id = (rlpxPeer.getId() as Buffer).toString('hex') + const id = bytesToHex(rlpxPeer.getId() as Uint8Array) const peer = this.peers.get(id) if (peer) { this.peers.delete(peer.id) @@ -282,7 +283,7 @@ export class RlpxServer extends Server { }) this.rlpx.on('peer:error', (rlpxPeer: Devp2pRLPxPeer, error: Error) => { - const peerId = rlpxPeer.getId() + const peerId = bytesToHex(rlpxPeer.getId() as Uint8Array) if (peerId === null) { return this.error(error) } diff --git a/packages/client/lib/net/server/server.ts b/packages/client/lib/net/server/server.ts index a745674ab7..b6ce4b942e 100644 --- a/packages/client/lib/net/server/server.ts +++ b/packages/client/lib/net/server/server.ts @@ -28,7 +28,7 @@ export interface ServerOptions { */ export class Server { public config: Config - public key: Buffer + public key: Uint8Array public bootnodes: Multiaddr[] = [] public dnsNetworks: DnsNetwork[] diff --git a/packages/client/lib/rpc/helpers.ts b/packages/client/lib/rpc/helpers.ts index 563377cbb3..6f01670724 100644 --- a/packages/client/lib/rpc/helpers.ts +++ b/packages/client/lib/rpc/helpers.ts @@ -1,4 +1,4 @@ -import { bigIntToHex, bufferToHex, intToHex } from '@ethereumjs/util' +import { bigIntToHex, bytesToPrefixedHexString, intToHex } from '@ethereumjs/util' import type { Block } from '@ethereumjs/block' import type { JsonRpcTx, TypedTransaction } from '@ethereumjs/tx' @@ -9,7 +9,7 @@ import type { JsonRpcTx, TypedTransaction } from '@ethereumjs/tx' export const jsonRpcTx = (tx: TypedTransaction, block?: Block, txIndex?: number): JsonRpcTx => { const txJSON = tx.toJSON() return { - blockHash: block ? bufferToHex(block.hash()) : null, + blockHash: block ? bytesToPrefixedHexString(block.hash()) : null, blockNumber: block ? bigIntToHex(block.header.number) : null, from: tx.getSenderAddress().toString(), gas: txJSON.gasLimit!, @@ -19,7 +19,7 @@ export const jsonRpcTx = (tx: TypedTransaction, block?: Block, txIndex?: number) type: intToHex(tx.type), accessList: txJSON.accessList, chainId: txJSON.chainId, - hash: bufferToHex(tx.hash()), + hash: bytesToPrefixedHexString(tx.hash()), input: txJSON.data!, nonce: txJSON.nonce!, to: tx.to?.toString() ?? null, diff --git a/packages/client/lib/rpc/modules/admin.ts b/packages/client/lib/rpc/modules/admin.ts index 37263f9ccc..443114c6c4 100644 --- a/packages/client/lib/rpc/modules/admin.ts +++ b/packages/client/lib/rpc/modules/admin.ts @@ -1,4 +1,4 @@ -import { bufferToHex } from '@ethereumjs/util' +import { bytesToHex } from '@ethereumjs/util' import { getClientVersion } from '../../util' import { middleware } from '../validation' @@ -41,8 +41,8 @@ export class Admin { const latestHeader = this._chain.headers.latest! const difficulty = latestHeader.difficulty.toString() - const genesis = bufferToHex(this._chain.genesis.hash()) - const head = bufferToHex(latestHeader.mixHash) + const genesis = bytesToHex(this._chain.genesis.hash()) + const head = bytesToHex(latestHeader.mixHash) const network = this._chain.networkId.toString() const nodeInfo = { diff --git a/packages/client/lib/rpc/modules/debug.ts b/packages/client/lib/rpc/modules/debug.ts index c36e2c3d90..680b530617 100644 --- a/packages/client/lib/rpc/modules/debug.ts +++ b/packages/client/lib/rpc/modules/debug.ts @@ -1,4 +1,4 @@ -import { bigIntToHex, bufferToHex, toBuffer } from '@ethereumjs/util' +import { bigIntToHex, bytesToPrefixedHexString, hexStringToBytes } from '@ethereumjs/util' import { INTERNAL_ERROR, INVALID_PARAMS } from '../error-code' import { middleware, validators } from '../validation' @@ -101,7 +101,7 @@ export class Debug { try { const result = await this.service.execution.receiptsManager.getReceiptByTxHash( - toBuffer(txHash) + hexStringToBytes(txHash) ) if (!result) return null const [_, blockHash, txIndex] = result @@ -131,7 +131,7 @@ export class Debug { } if (opts.enableMemory === true) { for (let x = 0; x < step.memoryWordCount; x++) { - const word = bufferToHex(step.memory.slice(x * 32, 32)) + const word = bytesToPrefixedHexString(step.memory.slice(x * 32, 32)) memory.push(word) } } @@ -142,8 +142,7 @@ export class Debug { gas: Number(step.gasLeft), depth: step.depth, error: null, - stack: - opts.disableStack !== true ? step.stack.map((entry) => bigIntToHex(entry)) : undefined, + stack: opts.disableStack !== true ? step.stack.map(bigIntToHex) : undefined, storage, memory, returnData: undefined, @@ -162,7 +161,7 @@ export class Debug { const res = await vmCopy.runTx({ tx, block }) trace.gas = bigIntToHex(res.totalGasSpent) trace.failed = res.execResult.exceptionError !== undefined - trace.returnValue = bufferToHex(res.execResult.returnValue) + trace.returnValue = bytesToPrefixedHexString(res.execResult.returnValue) return trace } catch (err: any) { throw { diff --git a/packages/client/lib/rpc/modules/engine.ts b/packages/client/lib/rpc/modules/engine.ts index 41f12fe909..a9810b8e38 100644 --- a/packages/client/lib/rpc/modules/engine.ts +++ b/packages/client/lib/rpc/modules/engine.ts @@ -1,7 +1,16 @@ import { Block } from '@ethereumjs/block' import { Hardfork } from '@ethereumjs/common' import { TransactionFactory } from '@ethereumjs/tx' -import { Withdrawal, bigIntToHex, bufferToHex, toBuffer, zeros } from '@ethereumjs/util' +import { + Withdrawal, + bigIntToHex, + bytesToHex, + bytesToPrefixedHexString, + equalsBytes, + hexStringToBytes, + toBytes, + zeros, +} from '@ethereumjs/util' import { PendingBlock } from '../../miner' import { short } from '../../util' @@ -163,7 +172,8 @@ const payloadAttributesFieldValidatorsV2 = { export const blockToExecutionPayload = (block: Block, value: bigint) => { const blockJson = block.toJSON() const header = blockJson.header! - const transactions = block.transactions.map((tx) => bufferToHex(tx.serialize())) ?? [] + const transactions = + block.transactions.map((tx) => bytesToPrefixedHexString(tx.serialize())) ?? [] const withdrawalsArr = blockJson.withdrawals ? { withdrawals: blockJson.withdrawals } : {} const executionPayload: ExecutionPayload = { @@ -179,7 +189,7 @@ export const blockToExecutionPayload = (block: Block, value: bigint) => { extraData: header.extraData!, baseFeePerGas: header.baseFeePerGas!, excessDataGas: header.excessDataGas, - blockHash: bufferToHex(block.hash()), + blockHash: bytesToPrefixedHexString(block.hash()), prevRandao: header.mixHash!, transactions, ...withdrawalsArr, @@ -190,14 +200,19 @@ export const blockToExecutionPayload = (block: Block, value: bigint) => { /** * Recursively finds parent blocks starting from the parentHash. */ -const recursivelyFindParents = async (vmHeadHash: Buffer, parentHash: Buffer, chain: Chain) => { - if (parentHash.equals(vmHeadHash) || parentHash.equals(Buffer.alloc(32))) { +const recursivelyFindParents = async ( + vmHeadHash: Uint8Array, + parentHash: Uint8Array, + chain: Chain +) => { + if (equalsBytes(parentHash, vmHeadHash) || equalsBytes(parentHash, new Uint8Array(32))) { return [] } + const parentBlocks = [] const block = await chain.getBlock(parentHash) parentBlocks.push(block) - while (!parentBlocks[parentBlocks.length - 1].hash().equals(parentHash)) { + while (!equalsBytes(parentBlocks[parentBlocks.length - 1].hash(), parentHash)) { const block: Block = await chain.getBlock( parentBlocks[parentBlocks.length - 1].header.parentHash ) @@ -209,19 +224,19 @@ const recursivelyFindParents = async (vmHeadHash: Buffer, parentHash: Buffer, ch /** * Returns the block hash as a 0x-prefixed hex string if found valid in the blockchain, otherwise returns null. */ -const validHash = async (hash: Buffer, chain: Chain): Promise => { +const validHash = async (hash: Uint8Array, chain: Chain): Promise => { try { await chain.getBlock(hash) } catch (error: any) { return null } - return bufferToHex(hash) + return bytesToPrefixedHexString(hash) } /** * Returns the block hash as a 0x-prefixed hex string if found valid in the blockchain, otherwise returns null. */ -const validBlock = async (hash: Buffer, chain: Chain): Promise => { +const validBlock = async (hash: Uint8Array, chain: Chain): Promise => { try { return await chain.getBlock(hash) } catch (error: any) { @@ -272,12 +287,12 @@ const assembleBlock = async ( const txs = [] for (const [index, serializedTx] of transactions.entries()) { try { - const tx = TransactionFactory.fromSerializedData(toBuffer(serializedTx), { common }) + const tx = TransactionFactory.fromSerializedData(hexStringToBytes(serializedTx), { common }) txs.push(tx) } catch (error) { const validationError = `Invalid tx at index ${index}: ${error}` config.logger.error(validationError) - const latestValidHash = await validHash(toBuffer(payload.parentHash), chain) + const latestValidHash = await validHash(hexStringToBytes(payload.parentHash), chain) const response = { status: Status.INVALID, latestValidHash, validationError } return { error: response } } @@ -302,19 +317,19 @@ const assembleBlock = async ( // correctly set to the correct hf block = Block.fromBlockData({ header, transactions: txs, withdrawals }, { common }) // Verify blockHash matches payload - if (!block.hash().equals(toBuffer(payload.blockHash))) { + if (!equalsBytes(block.hash(), hexStringToBytes(payload.blockHash))) { const validationError = `Invalid blockHash, expected: ${ payload.blockHash - }, received: ${bufferToHex(block.hash())}` + }, received: ${bytesToPrefixedHexString(block.hash())}` config.logger.debug(validationError) - const latestValidHash = null + const latestValidHash = await validHash(toBytes(header.parentHash), chain) const response = { status: Status.INVALID_BLOCK_HASH, latestValidHash, validationError } return { error: response } } } catch (error) { const validationError = `Error verifying block during init: ${error}` config.logger.debug(validationError) - const latestValidHash = await validHash(toBuffer(header.parentHash), chain) + const latestValidHash = await validHash(toBytes(header.parentHash), chain) const response = { status: Status.INVALID, latestValidHash, validationError } return { error: response } } @@ -323,7 +338,7 @@ const assembleBlock = async ( } const getPayloadBody = (block: Block): ExecutionPayloadBodyV1 => { - const transactions = block.transactions.map((tx) => bufferToHex(tx.serialize())) + const transactions = block.transactions.map((tx) => bytesToPrefixedHexString(tx.serialize())) const withdrawals = block.withdrawals?.map((wt) => wt.toJSON()) ?? null return { @@ -514,7 +529,7 @@ export class Engine { if (!response) { const validationError = `Error assembling block during init` this.config.logger.debug(validationError) - const latestValidHash = await validHash(toBuffer(payload.parentHash), this.chain) + const latestValidHash = await validHash(hexStringToBytes(payload.parentHash), this.chain) response = { status: Status.INVALID, latestValidHash, validationError } } return response @@ -538,7 +553,7 @@ export class Engine { // is pow block which this client would like to mint and attempt proposing it const optimisticLookup = await this.service.beaconSync?.extendChain(block) - const blockExists = await validBlock(toBuffer(blockHash), this.chain) + const blockExists = await validBlock(hexStringToBytes(blockHash), this.chain) if (blockExists) { const isBlockExecuted = await this.vm.stateManager.hasStateRoot(blockExists.header.stateRoot) if (isBlockExecuted) { @@ -552,14 +567,14 @@ export class Engine { } try { - const parent = await this.chain.getBlock(toBuffer(parentHash)) + const parent = await this.chain.getBlock(hexStringToBytes(parentHash)) if (!parent._common.gteHardfork(Hardfork.Merge)) { const validTerminalBlock = await validateTerminalBlock(parent, this.chain) if (!validTerminalBlock) { const response = { status: Status.INVALID, validationError: null, - latestValidHash: bufferToHex(zeros(32)), + latestValidHash: bytesToPrefixedHexString(zeros(32)), } return response } @@ -575,7 +590,7 @@ export class Engine { optimisticLookup === true ? Status.SYNCING : Status.ACCEPTED if (status === Status.ACCEPTED) { // Stash the block for a potential forced forkchoice update to it later. - this.remoteBlocks.set(block.hash().toString('hex'), block) + this.remoteBlocks.set(bytesToHex(block.hash()), block) } const response = { status, validationError: null, latestValidHash: null } return response @@ -620,11 +635,11 @@ export class Engine { return response } - this.remoteBlocks.set(block.hash().toString('hex'), block) + this.remoteBlocks.set(bytesToHex(block.hash()), block) const response = { status: Status.VALID, - latestValidHash: bufferToHex(block.hash()), + latestValidHash: bytesToPrefixedHexString(block.hash()), validationError: null, } return response @@ -723,10 +738,10 @@ export class Engine { const { headBlockHash, finalizedBlockHash, safeBlockHash } = params[0] const payloadAttributes = params[1] - const safe = toBuffer(safeBlockHash) - const finalized = toBuffer(finalizedBlockHash) + const safe = toBytes(safeBlockHash) + const finalized = toBytes(finalizedBlockHash) - if (!finalized.equals(zeroBlockHash) && safe.equals(zeroBlockHash)) { + if (!equalsBytes(finalized, zeroBlockHash) && equalsBytes(safe, zeroBlockHash)) { throw { code: INVALID_PARAMS, message: 'safe block can not be zero if finalized is not zero', @@ -749,10 +764,10 @@ export class Engine { */ let headBlock: Block | undefined try { - headBlock = await this.chain.getBlock(toBuffer(headBlockHash)) + headBlock = await this.chain.getBlock(toBytes(headBlockHash)) } catch (error) { headBlock = - (await this.service.beaconSync?.skeleton.getBlockByHash(toBuffer(headBlockHash))) ?? + (await this.service.beaconSync?.skeleton.getBlockByHash(toBytes(headBlockHash))) ?? this.remoteBlocks.get(headBlockHash.slice(2)) if (headBlock === undefined) { this.config.logger.debug(`Forkchoice requested unknown head hash=${short(headBlockHash)}`) @@ -796,7 +811,7 @@ export class Engine { payloadStatus: { status: Status.INVALID, validationError: null, - latestValidHash: bufferToHex(zeros(32)), + latestValidHash: bytesToHex(zeros(32)), }, payloadId: null, } @@ -822,8 +837,8 @@ export class Engine { */ let safeBlock, finalizedBlock - if (!safe.equals(zeroBlockHash)) { - if (safe.equals(headBlock.hash())) { + if (!equalsBytes(safe, zeroBlockHash)) { + if (equalsBytes(safe, headBlock.hash())) { safeBlock = headBlock } else { try { @@ -841,7 +856,7 @@ export class Engine { safeBlock = undefined } - if (!finalized.equals(zeroBlockHash)) { + if (!equalsBytes(finalized, zeroBlockHash)) { try { // Right now only check if the block is available, canonicality check is done // in setHead after chain.putBlocks so as to reflect latest canonical chain @@ -857,7 +872,7 @@ export class Engine { } const vmHeadHash = this.chain.headers.latest!.hash() - if (!vmHeadHash.equals(headBlock.hash())) { + if (!equalsBytes(vmHeadHash, headBlock.hash())) { let parentBlocks: Block[] = [] if (this.chain.headers.latest && this.chain.headers.latest.number < headBlock.header.number) { try { @@ -923,7 +938,7 @@ export class Engine { ) const latestValidHash = await validHash(headBlock.hash(), this.chain) const payloadStatus = { status: Status.VALID, latestValidHash, validationError: null } - const response = { payloadStatus, payloadId: bufferToHex(payloadId), headBlock } + const response = { payloadStatus, payloadId: bytesToPrefixedHexString(payloadId), headBlock } return response } @@ -979,7 +994,7 @@ export class Engine { * @returns Instance of {@link ExecutionPayloadV1} or an error */ private async getPayload(params: [Bytes8]) { - const payloadId = toBuffer(params[0]) + const payloadId = hexStringToBytes(params[0]) try { const built = await this.pendingBlock.build(payloadId) if (!built) { @@ -1057,8 +1072,8 @@ export class Engine { return { blockHash: bundle.blockHash, - kzgs: bundle.kzgCommitments.map((commitment) => '0x' + commitment.toString('hex')), - blobs: bundle.blobs.map((blob) => '0x' + blob.toString('hex')), + kzgs: bundle.kzgCommitments.map(bytesToPrefixedHexString), + blobs: bundle.blobs.map(bytesToPrefixedHexString), } } @@ -1085,7 +1100,7 @@ export class Engine { message: 'More than 32 execution payload bodies requested', } } - const hashes = params[0].map((hash) => toBuffer(hash)) + const hashes = params[0].map(hexStringToBytes) const blocks: (ExecutionPayloadBodyV1 | null)[] = [] for (const hash of hashes) { try { diff --git a/packages/client/lib/rpc/modules/eth.ts b/packages/client/lib/rpc/modules/eth.ts index 0ad46d3f0a..a8b16d7cde 100644 --- a/packages/client/lib/rpc/modules/eth.ts +++ b/packages/client/lib/rpc/modules/eth.ts @@ -4,11 +4,12 @@ import { Address, TypeOutput, bigIntToHex, - bufferToHex, + bytesToPrefixedHexString, + hexStringToBytes, intToHex, setLengthLeft, - toBuffer, toType, + utf8ToBytes, } from '@ethereumjs/util' import { INTERNAL_ERROR, INVALID_PARAMS, PARSE_ERROR } from '../error-code' @@ -83,7 +84,7 @@ const jsonRpcBlock = async ( const json = block.toJSON() const header = json!.header! const transactions = block.transactions.map((tx, txIndex) => - includeTransactions ? jsonRpcTx(tx, block, txIndex) : bufferToHex(tx.hash()) + includeTransactions ? jsonRpcTx(tx, block, txIndex) : bytesToPrefixedHexString(tx.hash()) ) const withdrawalsAttr = header.withdrawalsRoot !== undefined @@ -95,7 +96,7 @@ const jsonRpcBlock = async ( const td = await chain.getTd(block.hash(), block.header.number) return { number: header.number!, - hash: bufferToHex(block.hash()), + hash: bytesToPrefixedHexString(block.hash()), parentHash: header.parentHash!, mixHash: header.mixHash, nonce: header.nonce!, @@ -108,12 +109,12 @@ const jsonRpcBlock = async ( difficulty: header.difficulty!, totalDifficulty: bigIntToHex(td), extraData: header.extraData!, - size: intToHex(Buffer.byteLength(JSON.stringify(json))), + size: intToHex(utf8ToBytes(JSON.stringify(json)).byteLength), gasLimit: header.gasLimit!, gasUsed: header.gasUsed!, timestamp: header.timestamp!, transactions, - uncles: block.uncleHeaders.map((uh) => bufferToHex(uh.hash())), + uncles: block.uncleHeaders.map((uh) => bytesToPrefixedHexString(uh.hash())), baseFeePerGas: header.baseFeePerGas, ...withdrawalsAttr, excessDataGas: header.excessDataGas, @@ -133,12 +134,12 @@ const jsonRpcLog = async ( removed: false, // TODO implement logIndex: logIndex !== undefined ? intToHex(logIndex) : null, transactionIndex: txIndex !== undefined ? intToHex(txIndex) : null, - transactionHash: tx ? bufferToHex(tx.hash()) : null, - blockHash: block ? bufferToHex(block.hash()) : null, + transactionHash: tx ? bytesToPrefixedHexString(tx.hash()) : null, + blockHash: block ? bytesToPrefixedHexString(block.hash()) : null, blockNumber: block ? bigIntToHex(block.header.number) : null, - address: bufferToHex(log[0]), - topics: log[1].map((t) => bufferToHex(t as Buffer)), - data: bufferToHex(log[2]), + address: bytesToPrefixedHexString(log[0]), + topics: log[1].map(bytesToPrefixedHexString), + data: bytesToPrefixedHexString(log[2]), }) /** @@ -154,9 +155,9 @@ const jsonRpcReceipt = async ( logIndex: number, contractAddress?: Address ): Promise => ({ - transactionHash: bufferToHex(tx.hash()), + transactionHash: bytesToPrefixedHexString(tx.hash()), transactionIndex: intToHex(txIndex), - blockHash: bufferToHex(block.hash()), + blockHash: bytesToPrefixedHexString(block.hash()), blockNumber: bigIntToHex(block.header.number), from: tx.getSenderAddress().toString(), to: tx.to?.toString() ?? null, @@ -167,13 +168,15 @@ const jsonRpcReceipt = async ( logs: await Promise.all( receipt.logs.map((l, i) => jsonRpcLog(l, block, tx, txIndex, logIndex + i)) ), - logsBloom: bufferToHex(receipt.bitvector), - root: Buffer.isBuffer((receipt as PreByzantiumTxReceipt).stateRoot) - ? bufferToHex((receipt as PreByzantiumTxReceipt).stateRoot) - : undefined, - status: Buffer.isBuffer((receipt as PostByzantiumTxReceipt).status) - ? intToHex((receipt as PostByzantiumTxReceipt).status) - : undefined, + logsBloom: bytesToPrefixedHexString(receipt.bitvector), + root: + (receipt as PreByzantiumTxReceipt).stateRoot instanceof Uint8Array + ? bytesToPrefixedHexString((receipt as PreByzantiumTxReceipt).stateRoot) + : undefined, + status: + ((receipt as PostByzantiumTxReceipt).status as unknown) instanceof Uint8Array + ? intToHex((receipt as PostByzantiumTxReceipt).status) + : undefined, }) /** @@ -401,10 +404,10 @@ export class Eth { gasLimit: toType(gasLimit, TypeOutput.BigInt), gasPrice: toType(gasPrice, TypeOutput.BigInt), value: toType(value, TypeOutput.BigInt), - data: data !== undefined ? toBuffer(data) : undefined, + data: data !== undefined ? hexStringToBytes(data) : undefined, } const { execResult } = await vm.evm.runCall(runCallOpts) - return bufferToHex(execResult.returnValue) + return bytesToPrefixedHexString(execResult.returnValue) } catch (error: any) { throw { code: INTERNAL_ERROR, @@ -527,7 +530,7 @@ export class Eth { const [blockHash, includeTransactions] = params try { - const block = await this._chain.getBlock(toBuffer(blockHash)) + const block = await this._chain.getBlock(hexStringToBytes(blockHash)) return await jsonRpcBlock(block, this._chain, includeTransactions) } catch (error) { throw { @@ -556,7 +559,7 @@ export class Eth { async getBlockTransactionCountByHash(params: [string]) { const [blockHash] = params try { - const block = await this._chain.getBlock(toBuffer(blockHash)) + const block = await this._chain.getBlock(hexStringToBytes(blockHash)) return intToHex(block.transactions.length) } catch (error) { throw { @@ -585,7 +588,7 @@ export class Eth { const address = Address.fromString(addressHex) const code = await vm.stateManager.getContractCode(address) - return bufferToHex(code) + return bytesToPrefixedHexString(code) } /** @@ -608,11 +611,11 @@ export class Eth { const address = Address.fromString(addressHex) const storageTrie = await (vm.stateManager as any)._getStorageTrie(address) - const position = setLengthLeft(toBuffer(positionHex), 32) + const position = setLengthLeft(hexStringToBytes(positionHex), 32) const storage = await storageTrie.get(position) return storage !== null && storage !== undefined - ? bufferToHex( - setLengthLeft(Buffer.from(RLP.decode(Uint8Array.from(storage)) as Uint8Array), 32) + ? bytesToPrefixedHexString( + setLengthLeft(RLP.decode(Uint8Array.from(storage)) as Uint8Array, 32) ) : '0x' } @@ -627,7 +630,7 @@ export class Eth { try { const [blockHash, txIndexHex] = params const txIndex = parseInt(txIndexHex, 16) - const block = await this._chain.getBlock(toBuffer(blockHash)) + const block = await this._chain.getBlock(hexStringToBytes(blockHash)) if (block.transactions.length <= txIndex) { return null } @@ -652,7 +655,7 @@ export class Eth { try { if (!this.receiptsManager) throw new Error('missing receiptsManager') - const result = await this.receiptsManager.getReceiptByTxHash(toBuffer(txHash)) + const result = await this.receiptsManager.getReceiptByTxHash(hexStringToBytes(txHash)) if (!result) return null const [_receipt, blockHash, txIndex] = result const block = await this._chain.getBlock(blockHash) @@ -732,7 +735,7 @@ export class Eth { try { if (!this.receiptsManager) throw new Error('missing receiptsManager') - const result = await this.receiptsManager.getReceiptByTxHash(toBuffer(txHash)) + const result = await this.receiptsManager.getReceiptByTxHash(hexStringToBytes(txHash)) if (!result) return null const [receipt, blockHash, txIndex, logIndex] = result const block = await this._chain.getBlock(blockHash) @@ -791,7 +794,7 @@ export class Eth { let from: Block, to: Block if (blockHash !== undefined) { try { - from = to = await this._chain.getBlock(toBuffer(blockHash)) + from = to = await this._chain.getBlock(hexStringToBytes(blockHash)) } catch (error: any) { throw { code: INVALID_PARAMS, @@ -842,17 +845,17 @@ export class Eth { if (t === null) { return null } else if (Array.isArray(t)) { - return t.map((x) => toBuffer(x)) + return t.map((x) => hexStringToBytes(x)) } else { - return toBuffer(t) + return hexStringToBytes(t) } }) let addrs if (address !== undefined) { if (Array.isArray(address)) { - addrs = address.map((a) => toBuffer(a)) + addrs = address.map((a) => hexStringToBytes(a)) } else { - addrs = [toBuffer(address)] + addrs = [hexStringToBytes(address)] } } const logs = await this.receiptsManager.getLogs(from, to, addrs, formattedTopics) @@ -896,7 +899,7 @@ export class Eth { let tx try { - const txBuf = toBuffer(serializedTx) + const txBuf = hexStringToBytes(serializedTx) if (txBuf[0] === 0x05) { // Blob Transactions sent over RPC are expected to be in Network Wrapper format tx = BlobEIP4844Transaction.fromSerializedBlobTxNetworkWrapper(txBuf, { common }) @@ -943,7 +946,7 @@ export class Eth { } txPool.sendTransactions([tx], peerPool.peers) - return bufferToHex(tx.hash()) + return bytesToPrefixedHexString(tx.hash()) } /** @@ -970,7 +973,7 @@ export class Eth { await vm.stateManager.setStateRoot(block.header.stateRoot) const address = Address.fromString(addressHex) - const slots = slotsHex.map((slotHex) => setLengthLeft(toBuffer(slotHex), 32)) + const slots = slotsHex.map((slotHex) => setLengthLeft(hexStringToBytes(slotHex), 32)) const proof = await vm.stateManager.getProof!(address, slots) return proof } diff --git a/packages/client/lib/rpc/modules/web3.ts b/packages/client/lib/rpc/modules/web3.ts index 6212413d86..31f5a03131 100644 --- a/packages/client/lib/rpc/modules/web3.ts +++ b/packages/client/lib/rpc/modules/web3.ts @@ -1,4 +1,4 @@ -import { addHexPrefix, toBuffer } from '@ethereumjs/util' +import { addHexPrefix, toBytes } from '@ethereumjs/util' import { keccak256 } from 'ethereum-cryptography/keccak' import { bytesToHex } from 'ethereum-cryptography/utils' @@ -42,7 +42,7 @@ export class Web3 { * @param params The data to convert into a SHA3 hash */ sha3(params: string[]) { - const hexEncodedDigest = addHexPrefix(bytesToHex(keccak256(toBuffer(params[0])))) + const hexEncodedDigest = addHexPrefix(bytesToHex(keccak256(toBytes(params[0])))) return hexEncodedDigest } } diff --git a/packages/client/lib/service/ethereumservice.ts b/packages/client/lib/service/ethereumservice.ts index a1c39ea525..f783156441 100644 --- a/packages/client/lib/service/ethereumservice.ts +++ b/packages/client/lib/service/ethereumservice.ts @@ -12,13 +12,13 @@ export interface EthereumServiceOptions extends ServiceOptions { chain: Chain /* Blockchain database */ - chainDB?: AbstractLevel + chainDB?: AbstractLevel /* State database */ - stateDB?: AbstractLevel + stateDB?: AbstractLevel /* Meta database (receipts, logs, indexes) */ - metaDB?: AbstractLevel + metaDB?: AbstractLevel /* Sync retry interval in ms (default: 8000) */ interval?: number diff --git a/packages/client/lib/service/fullethereumservice.ts b/packages/client/lib/service/fullethereumservice.ts index 838cce0d81..0c48f37aec 100644 --- a/packages/client/lib/service/fullethereumservice.ts +++ b/packages/client/lib/service/fullethereumservice.ts @@ -1,5 +1,6 @@ import { Hardfork } from '@ethereumjs/common' import { encodeReceipt } from '@ethereumjs/vm/dist/runBlock' +import { concatBytes } from 'ethereum-cryptography/utils' import { VMExecution } from '../execution' import { Miner } from '../miner' @@ -256,7 +257,7 @@ export class FullEthereumService extends EthereumService { case 'GetBlockBodies': { const { reqId, hashes } = message.data const blocks: Block[] = await Promise.all( - hashes.map((hash: Buffer) => this.chain.getBlock(hash)) + hashes.map((hash: Uint8Array) => this.chain.getBlock(hash)) ) const bodies = blocks.map((block) => block.raw().slice(1)) peer.eth!.send('BlockBodies', { reqId, bodies }) @@ -309,8 +310,8 @@ export class FullEthereumService extends EthereumService { const blockReceipts = await receiptsManager.getReceipts(hash, true, true) if (blockReceipts === undefined) continue receipts.push(...blockReceipts) - const receiptsBuffer = Buffer.concat(receipts.map((r) => encodeReceipt(r, r.txType))) - receiptsSize += Buffer.byteLength(receiptsBuffer) + const receiptsBytes = concatBytes(...receipts.map((r) => encodeReceipt(r, r.txType))) + receiptsSize += receiptsBytes.byteLength // From spec: The recommended soft limit for Receipts responses is 2 MiB. if (receiptsSize >= 2097152) { break diff --git a/packages/client/lib/service/txpool.ts b/packages/client/lib/service/txpool.ts index 48fa899c9b..475f779efb 100644 --- a/packages/client/lib/service/txpool.ts +++ b/packages/client/lib/service/txpool.ts @@ -1,5 +1,5 @@ import { BlobEIP4844Transaction, Capability } from '@ethereumjs/tx' -import { Address, bufferToHex } from '@ethereumjs/util' +import { Address, bytesToHex, equalsBytes, hexStringToBytes } from '@ethereumjs/util' import Heap = require('qheap') import type { Config } from '../config' @@ -279,8 +279,8 @@ export class TxPool { // Replace pooled txs with the same nonce const existingTxn = inPool.find((poolObj) => poolObj.tx.nonce === tx.nonce) if (existingTxn) { - if (existingTxn.tx.hash().equals(tx.hash())) { - throw new Error(`${bufferToHex(tx.hash())}: this transaction is already in the TxPool`) + if (equalsBytes(existingTxn.tx.hash(), tx.hash())) { + throw new Error(`${bytesToHex(tx.hash())}: this transaction is already in the TxPool`) } this.validateTxGasBump(existingTxn.tx, tx) } @@ -327,7 +327,7 @@ export class TxPool { * @param isLocalTransaction if this is a local transaction (loosens some constraints) (default: false) */ async add(tx: TypedTransaction, isLocalTransaction: boolean = false) { - const hash: UnprefixedHash = tx.hash().toString('hex') + const hash: UnprefixedHash = bytesToHex(tx.hash()) const added = Date.now() const address: UnprefixedAddress = tx.getSenderAddress().toString().slice(2) try { @@ -353,10 +353,10 @@ export class TxPool { * @param txHashes * @returns Array with tx objects */ - getByHash(txHashes: Buffer[]): TypedTransaction[] { + getByHash(txHashes: Uint8Array[]): TypedTransaction[] { const found = [] for (const txHash of txHashes) { - const txHashStr = txHash.toString('hex') + const txHashStr = bytesToHex(txHash) const handled = this.handled.get(txHashStr) if (!handled) continue const inPool = this.pool.get(handled.address)?.filter((poolObj) => poolObj.hash === txHashStr) @@ -395,21 +395,21 @@ export class TxPool { * @param peer * @returns Array with txs which are new to the list */ - addToKnownByPeer(txHashes: Buffer[], peer: Peer): Buffer[] { + addToKnownByPeer(txHashes: Uint8Array[], peer: Peer): Uint8Array[] { // Make sure data structure is initialized if (!this.knownByPeer.has(peer.id)) { this.knownByPeer.set(peer.id, []) } - const newHashes: Buffer[] = [] + const newHashes: Uint8Array[] = [] for (const hash of txHashes) { const inSent = this.knownByPeer .get(peer.id)! - .filter((sentObject) => sentObject.hash === hash.toString('hex')).length + .filter((sentObject) => sentObject.hash === bytesToHex(hash)).length if (inSent === 0) { const added = Date.now() const add = { - hash: hash.toString('hex'), + hash: bytesToHex(hash), added, } this.knownByPeer.get(peer.id)!.push(add) @@ -428,7 +428,7 @@ export class TxPool { * @param txHashes Array with transactions to send * @param peers */ - async sendNewTxHashes(txHashes: Buffer[], peers: Peer[]) { + async sendNewTxHashes(txHashes: Uint8Array[], peers: Peer[]) { for (const peer of peers) { // Make sure data structure is initialized if (!this.knownByPeer.has(peer.id)) { @@ -464,8 +464,8 @@ export class TxPool { // This is used to avoid re-sending along pooledTxHashes // announcements/re-broadcasts const newHashes = this.addToKnownByPeer(hashes, peer) - const newHashesHex = newHashes.map((txHash) => txHash.toString('hex')) - const newTxs = txs.filter((tx) => newHashesHex.includes(tx.hash().toString('hex'))) + const newHashesHex = newHashes.map((txHash) => bytesToHex(txHash)) + const newTxs = txs.filter((tx) => newHashesHex.includes(bytesToHex(tx.hash()))) peer.eth?.request('Transactions', newTxs).catch((e) => { this.markFailedSends(peer, newHashes, e as Error) }) @@ -473,11 +473,11 @@ export class TxPool { } } - private markFailedSends(peer: Peer, failedHashes: Buffer[], e: Error): void { + private markFailedSends(peer: Peer, failedHashes: Uint8Array[], e: Error): void { for (const txHash of failedHashes) { const sendobject = this.knownByPeer .get(peer.id) - ?.filter((sendObject) => sendObject.hash === txHash.toString('hex'))[0] + ?.filter((sendObject) => sendObject.hash === bytesToHex(txHash))[0] if (sendobject) { sendobject.error = e } @@ -506,7 +506,7 @@ export class TxPool { newTxHashes.push(tx.hash()) } catch (error: any) { this.config.logger.debug( - `Error adding tx to TxPool: ${error.message} (tx hash: ${bufferToHex(tx.hash())})` + `Error adding tx to TxPool: ${error.message} (tx hash: ${bytesToHex(tx.hash())})` ) } } @@ -524,13 +524,13 @@ export class TxPool { * @param peer Announcing peer * @param peerPool Reference to the peer pool */ - async handleAnnouncedTxHashes(txHashes: Buffer[], peer: Peer, peerPool: PeerPool) { + async handleAnnouncedTxHashes(txHashes: Uint8Array[], peer: Peer, peerPool: PeerPool) { if (!this.running || txHashes.length === 0) return this.addToKnownByPeer(txHashes, peer) const reqHashes = [] for (const txHash of txHashes) { - const txHashStr: UnprefixedHash = txHash.toString('hex') + const txHashStr: UnprefixedHash = bytesToHex(txHash) if (this.pending.includes(txHashStr) || this.handled.has(txHashStr)) { continue } @@ -541,7 +541,7 @@ export class TxPool { this.config.logger.debug(`TxPool: received new tx hashes number=${reqHashes.length}`) - const reqHashesStr: UnprefixedHash[] = reqHashes.map((hash) => hash.toString('hex')) + const reqHashesStr: UnprefixedHash[] = reqHashes.map(bytesToHex) this.pending = this.pending.concat(reqHashesStr) this.config.logger.debug( `TxPool: requesting txs number=${reqHashes.length} pending=${this.pending.length}` @@ -565,7 +565,7 @@ export class TxPool { await this.add(tx) } catch (error: any) { this.config.logger.debug( - `Error adding tx to TxPool: ${error.message} (tx hash: ${bufferToHex(tx.hash())})` + `Error adding tx to TxPool: ${error.message} (tx hash: ${bytesToHex(tx.hash())})` ) } newTxHashes.push(tx.hash()) @@ -580,7 +580,7 @@ export class TxPool { if (!this.running) return for (const block of newBlocks) { for (const tx of block.transactions) { - const txHash: UnprefixedHash = tx.hash().toString('hex') + const txHash: UnprefixedHash = bytesToHex(tx.hash()) this.removeByHash(txHash) } } @@ -694,7 +694,7 @@ export class TxPool { .map((obj) => obj.tx) .sort((a, b) => Number(a.nonce - b.nonce)) // Check if the account nonce matches the lowest known tx nonce - const { nonce } = await vm.eei.getAccount(new Address(Buffer.from(address, 'hex'))) + const { nonce } = await vm.eei.getAccount(new Address(hexStringToBytes(address))) if (txsSortedByNonce[0].nonce !== nonce) { // Account nonce does not match the lowest known tx nonce, // therefore no txs from this address are currently executable diff --git a/packages/client/lib/sync/beaconsync.ts b/packages/client/lib/sync/beaconsync.ts index a1c727e32b..c67705c06a 100644 --- a/packages/client/lib/sync/beaconsync.ts +++ b/packages/client/lib/sync/beaconsync.ts @@ -1,3 +1,5 @@ +import { bytesToHex } from 'ethereum-cryptography/utils' + import { Event } from '../types' import { short } from '../util' @@ -76,8 +78,8 @@ export class BeaconSynchronizer extends Synchronizer { this.config.chainCommon.setHardforkByBlockNumber(number, td, timestamp) this.config.logger.info( - `Latest local block number=${Number(number)} td=${td} hash=${hash.toString( - 'hex' + `Latest local block number=${Number(number)} td=${td} hash=${bytesToHex( + hash )} hardfork=${this.config.chainCommon.hardfork()}` ) diff --git a/packages/client/lib/sync/fetcher/accountfetcher.ts b/packages/client/lib/sync/fetcher/accountfetcher.ts index 8349803a5b..5ef539f596 100644 --- a/packages/client/lib/sync/fetcher/accountfetcher.ts +++ b/packages/client/lib/sync/fetcher/accountfetcher.ts @@ -3,10 +3,10 @@ import { KECCAK256_NULL_S, KECCAK256_RLP, accountBodyToRLP, - bigIntToBuffer, - bufArrToArr, - bufferToBigInt, - bufferToHex, + bigIntToBytes, + bytesToBigInt, + bytesToHex, + equalsBytes, setLengthLeft, } from '@ethereumjs/util' import { debug as createDebugLogger } from 'debug' @@ -35,7 +35,7 @@ type AccountDataResponse = AccountData[] & { completed?: boolean } */ export interface AccountFetcherOptions extends FetcherOptions { /** Root hash of the account trie to serve */ - root: Buffer + root: Uint8Array /** The origin to start account fetcher from */ first: bigint @@ -60,13 +60,13 @@ export type FetcherDoneFlags = { accountFetcherDone: boolean byteCodeFetcherDone: boolean eventBus?: EventBusType | undefined - stateRoot?: Buffer | undefined + stateRoot?: Uint8Array | undefined } export function snapFetchersCompleted( fetcherDoneFlags: FetcherDoneFlags, fetcherType: Object, - root?: Buffer, + root?: Uint8Array, eventBus?: EventBusType ) { switch (fetcherType) { @@ -90,7 +90,7 @@ export function snapFetchersCompleted( ) { fetcherDoneFlags.eventBus!.emit( Event.SYNC_SNAPSYNC_COMPLETE, - bufArrToArr(fetcherDoneFlags.stateRoot as Buffer) + bufArrToArr(fetcherDoneFlags.stateRoot!) ) } } @@ -102,7 +102,7 @@ export class AccountFetcher extends Fetcher * The stateRoot for the fetcher which sorts of pin it to a snapshot. * This might eventually be removed as the snapshots are moving and not static */ - root: Buffer + root: Uint8Array /** The origin to start account fetcher from (including), by default starts from 0 (0x0000...) */ first: bigint @@ -184,19 +184,19 @@ export class AccountFetcher extends Fetcher } private async verifyRangeProof( - stateRoot: Buffer, - origin: Buffer, - { accounts, proof }: { accounts: AccountData[]; proof: Buffer[] } + stateRoot: Uint8Array, + origin: Uint8Array, + { accounts, proof }: { accounts: AccountData[]; proof: Uint8Array[] } ): Promise { this.debug( - `verifyRangeProof accounts:${accounts.length} first=${bufferToHex( + `verifyRangeProof accounts:${accounts.length} first=${bytesToHex( accounts[0].hash )} last=${short(accounts[accounts.length - 1].hash)}` ) for (let i = 0; i < accounts.length - 1; i++) { // ensure the range is monotonically increasing - if (accounts[i].hash.compare(accounts[i + 1].hash) === 1) { + if (bytesToBigInt(accounts[i].hash) > bytesToBigInt(accounts[i + 1].hash)) { throw Error( `Account hashes not monotonically increasing: ${i} ${accounts[i].hash} vs ${i + 1} ${ accounts[i + 1].hash @@ -212,28 +212,32 @@ export class AccountFetcher extends Fetcher return trie.verifyRangeProof(stateRoot, origin, keys[keys.length - 1], keys, values, proof) } - private getOrigin(job: Job): Buffer { + private getOrigin(job: Job): Uint8Array { const { task, partialResult } = job const { first } = task // Snap protocol will automatically pad it with 32 bytes left, so we don't need to worry const origin = partialResult - ? bigIntToBuffer(bufferToBigInt(partialResult[partialResult.length - 1].hash) + BigInt(1)) - : bigIntToBuffer(first) + ? bigIntToBytes(bytesToBigInt(partialResult[partialResult.length - 1].hash) + BigInt(1)) + : bigIntToBytes(first) return setLengthLeft(origin, 32) } - private getLimit(job: Job): Buffer { + private getLimit(job: Job): Uint8Array { const { task } = job const { first, count } = task - const limit = bigIntToBuffer(first + BigInt(count) - BigInt(1)) + const limit = bigIntToBytes(first + BigInt(count) - BigInt(1)) return setLengthLeft(limit, 32) } private isMissingRightRange( - limit: Buffer, - { accounts, proof: _proof }: { accounts: AccountData[]; proof: Buffer[] } + limit: Uint8Array, + { accounts, proof: _proof }: { accounts: AccountData[]; proof: Uint8Array[] } ): boolean { - if (accounts.length > 0 && accounts[accounts.length - 1]?.hash.compare(limit) >= 0) { + if ( + accounts.length > 0 && + accounts[accounts.length - 1] !== undefined && + bytesToBigInt(accounts[accounts.length - 1].hash) >= bytesToBigInt(limit) + ) { return false } else { // TODO: Check if there is a proof of missing limit in state @@ -267,7 +271,7 @@ export class AccountFetcher extends Fetcher if ( rangeResult.accounts.length === 0 || - limit.compare(bigIntToBuffer(BigInt(2) ** BigInt(256))) === 0 + equalsBytes(limit, bigIntToBytes(BigInt(2) ** BigInt(256))) === true ) { // TODO have to check proof of nonexistence -- as a shortcut for now, we can mark as completed if a proof is present if (rangeResult.proof.length > 0) { @@ -288,9 +292,9 @@ export class AccountFetcher extends Fetcher let completed: boolean if (isMissingRightRange && this.isMissingRightRange(limit, rangeResult)) { this.debug( - `Peer ${peerInfo} returned missing right range account=${rangeResult.accounts[ - rangeResult.accounts.length - 1 - ].hash.toString('hex')} limit=${limit.toString('hex')}` + `Peer ${peerInfo} returned missing right range account=${bytesToHex( + rangeResult.accounts[rangeResult.accounts.length - 1].hash + )} limit=${bytesToHex(limit)}` ) completed = false } else { @@ -353,10 +357,10 @@ export class AccountFetcher extends Fetcher await this.accountTrie.put(account.hash, accountBodyToRLP(account.body)) // build record of accounts that need storage slots to be fetched - const storageRoot: Buffer = - account.body[2] instanceof Buffer ? account.body[2] : Buffer.from(account.body[2]) - if (storageRoot.compare(KECCAK256_RLP) !== 0) { - storageFetchRequests.add({ + const storageRoot: Uint8Array = + account.body[2] instanceof Uint8Array ? account.body[2] : Uint8Array.from(account.body[2]) + if (equalsBytes(storageRoot, KECCAK256_RLP)) { + storageFetchRequests.push({ accountHash: account.hash, storageRoot, first: BigInt(0), @@ -391,7 +395,7 @@ export class AccountFetcher extends Fetcher tasks(first = this.first, count = this.count, maxTasks = this.config.maxFetcherJobs): JobTask[] { const max = this.config.maxAccountRange const tasks: JobTask[] = [] - let debugStr = `origin=${short(setLengthLeft(bigIntToBuffer(first), 32))}` + let debugStr = `origin=${short(setLengthLeft(bigIntToBytes(first), 32))}` let pushedCount = BigInt(0) const startedWith = first @@ -416,7 +420,7 @@ export class AccountFetcher extends Fetcher } debugStr += ` limit=${short( - setLengthLeft(bigIntToBuffer(startedWith + pushedCount - BigInt(1)), 32) + setLengthLeft(bigIntToBytes(startedWith + pushedCount - BigInt(1)), 32) )}` this.debug(`Created new tasks num=${tasks.length} ${debugStr}`) return tasks diff --git a/packages/client/lib/sync/fetcher/blockfetcher.ts b/packages/client/lib/sync/fetcher/blockfetcher.ts index 14141eadcd..5b7cdba2bc 100644 --- a/packages/client/lib/sync/fetcher/blockfetcher.ts +++ b/packages/client/lib/sync/fetcher/blockfetcher.ts @@ -1,5 +1,5 @@ import { Block } from '@ethereumjs/block' -import { KECCAK256_RLP, KECCAK256_RLP_ARRAY } from '@ethereumjs/util' +import { KECCAK256_RLP, KECCAK256_RLP_ARRAY, equalsBytes } from '@ethereumjs/util' import { Event } from '../../types' @@ -8,7 +8,7 @@ import { BlockFetcherBase } from './blockfetcherbase' import type { Peer } from '../../net/peer' import type { BlockFetcherOptions, JobTask } from './blockfetcherbase' import type { Job } from './types' -import type { BlockBuffer } from '@ethereumjs/block' +import type { BlockBytes } from '@ethereumjs/block' /** * Implements an eth/66 based block fetcher @@ -69,10 +69,10 @@ export class BlockFetcher extends BlockFetcherBase { for (const [i, [txsData, unclesData, withdrawalsData]] of bodies.entries()) { const header = headers[i] if ( - (!header.transactionsTrie.equals(KECCAK256_RLP) && txsData.length === 0) || - (!header.uncleHash.equals(KECCAK256_RLP_ARRAY) && unclesData.length === 0) || + (!equalsBytes(header.transactionsTrie, KECCAK256_RLP) && txsData.length === 0) || + (!equalsBytes(header.uncleHash, KECCAK256_RLP_ARRAY) && unclesData.length === 0) || (header.withdrawalsRoot !== undefined && - !header.withdrawalsRoot.equals(KECCAK256_RLP) && + !equalsBytes(header.withdrawalsRoot, KECCAK256_RLP) && (withdrawalsData?.length ?? 0) === 0) ) { this.debug( @@ -80,7 +80,7 @@ export class BlockFetcher extends BlockFetcherBase { ) return [] } - const values: BlockBuffer = [headers[i].raw(), txsData, unclesData] + const values: BlockBytes = [headers[i].raw(), txsData, unclesData] if (withdrawalsData !== undefined) { values.push(withdrawalsData) } diff --git a/packages/client/lib/sync/fetcher/storagefetcher.ts b/packages/client/lib/sync/fetcher/storagefetcher.ts index 512ed0fd54..672c125144 100644 --- a/packages/client/lib/sync/fetcher/storagefetcher.ts +++ b/packages/client/lib/sync/fetcher/storagefetcher.ts @@ -1,9 +1,10 @@ import { Trie } from '@ethereumjs/trie' import { - bigIntToBuffer, + bigIntToBytes, bigIntToHex, - bufferToBigInt, - bufferToHex, + bytesToBigInt, + bytesToHex, + equalsBytes, setLengthLeft, } from '@ethereumjs/util' import { debug as createDebugLogger } from 'debug' @@ -24,8 +25,8 @@ const TOTAL_RANGE_END = BigInt(2) ** BigInt(256) - BigInt(1) type StorageDataResponse = StorageData[][] & { completed?: boolean } export type StorageRequest = { - accountHash: Buffer - storageRoot: Buffer + accountHash: Uint8Array + storageRoot: Uint8Array first: bigint count: bigint } @@ -36,7 +37,7 @@ export type StorageRequest = { */ export interface StorageFetcherOptions extends FetcherOptions { /** Root hash of the account trie to serve */ - root: Buffer + root: Uint8Array /** Storage requests to fetch */ storageRequests?: StorageRequest[] @@ -64,7 +65,7 @@ export class StorageFetcher extends Fetcher { try { this.debug( @@ -115,7 +116,7 @@ export class StorageFetcher extends Fetcher bytesToBigInt(slots[i + 1].hash)) { throw Error( `Account hashes not monotonically increasing: ${i} ${slots[i].hash} vs ${i + 1} ${ slots[i + 1].hash @@ -141,12 +142,12 @@ export class StorageFetcher extends Fetcher { + private async verifySlots(slots: StorageData[], root: Uint8Array): Promise { try { this.debug(`verify ${slots.length} slots`) for (let i = 0; i < slots.length - 1; i++) { // ensure the range is monotonically increasing - if (slots[i].hash.compare(slots[i + 1].hash) === 1) { + if (bytesToBigInt(slots[i].hash) > bytesToBigInt(slots[i + 1].hash)) { throw Error( `Account hashes not monotonically increasing: ${i} ${slots[i].hash} vs ${i + 1} ${ slots[i + 1].hash @@ -164,7 +165,7 @@ export class StorageFetcher extends Fetcher): Buffer { + private getOrigin(job: Job): Uint8Array { const { task, partialResult } = job if (task.storageRequests.length > 1 || task.storageRequests[0].first === BigInt(0)) { // peer does not respect origin or limit for multi-account storage fetch - return setLengthLeft(bigIntToBuffer(BigInt(0)), 32) + return setLengthLeft(bigIntToBytes(BigInt(0)), 32) } const { first } = task.storageRequests[0]! let origin = undefined if (partialResult) { const lastSlotArray = partialResult[partialResult.length - 1] const lastSlot = lastSlotArray[lastSlotArray.length - 1] - origin = bigIntToBuffer(bufferToBigInt(lastSlot.hash) + BigInt(1)) + origin = bigIntToBytes(bytesToBigInt(lastSlot.hash) + BigInt(1)) } else { - origin = bigIntToBuffer(first + BigInt(1)) + origin = bigIntToBytes(first + BigInt(1)) } return setLengthLeft(origin, 32) } - private getLimit(job: Job): Buffer { + private getLimit(job: Job): Uint8Array { const { task } = job if (task.storageRequests.length > 1) { // peer does not respect origin or limit for multi-account storage fetch - return setLengthLeft(bigIntToBuffer(TOTAL_RANGE_END), 32) + return setLengthLeft(bigIntToBytes(TOTAL_RANGE_END), 32) } const { first, count } = task.storageRequests[0] - const limit = bigIntToBuffer((first + (BigInt(count as any) as any)) as any) + const limit = bigIntToBytes((first + (BigInt(count as any) as any)) as any) return setLengthLeft(limit, 32) } private isMissingRightRange( - limit: Buffer, - { slots, proof: _proof }: { slots: StorageData[][]; proof: Buffer[] } + limit: Uint8Array, + { slots, proof: _proof }: { slots: StorageData[][]; proof: Uint8Array[] } ): boolean { - if (slots.length > 0 && slots[0][slots[0].length - 1]?.hash.compare(limit) >= 0) { + if ( + slots.length > 0 && + slots[0][slots[0].length - 1] !== undefined && + bytesToBigInt(slots[0][slots[0].length - 1].hash) >= bytesToBigInt(limit) + ) { return false } else { return true @@ -230,11 +235,11 @@ export class StorageFetcher extends Fetcher bufferToHex(req.accountHash))}` + `requested account hashes: ${task.storageRequests.map((req) => bytesToHex(req.accountHash))}` ) const rangeResult = await peer!.snap!.getStorageRanges({ @@ -308,9 +313,9 @@ export class StorageFetcher extends Fetcher { const accountHash = result.requests[i].accountHash const storageTrie = - this.accountToStorageTrie.get(bufferToHex(accountHash)) ?? + this.accountToStorageTrie.get(bytesToHex(accountHash)) ?? new Trie({ useKeyHashing: false }) for (const slot of slotArray as any) { slotCount++ void storageTrie.put(slot.hash, slot.body) } - this.accountToStorageTrie.set(bufferToHex(accountHash), storageTrie) + this.accountToStorageTrie.set(bytesToHex(accountHash), storageTrie) }) this.debug(`Stored ${slotCount} slot(s)`) } catch (err) { @@ -462,7 +467,7 @@ export class StorageFetcher extends Fetcher= BigInt(max) && tasks.length < maxTasks) { const task = { @@ -512,7 +517,7 @@ export class StorageFetcher extends Fetcher knownBlock.hash.equals(blockHash))) { + if (knownBlocks.find((knownBlock) => equalsBytes(knownBlock.hash, blockHash))) { return true } knownBlocks.push({ hash: blockHash, added: Date.now() }) @@ -321,7 +322,11 @@ export class FullSynchronizer extends Synchronizer { // https://github.com/ethereum/devp2p/blob/master/caps/eth.md#block-propagation const numPeersToShareWith = Math.floor(Math.sqrt(this.pool.peers.length)) await this.sendNewBlock(block, this.pool.peers.slice(0, numPeersToShareWith)) - if (this.chain.blocks.latest?.hash().equals(block.header.parentHash) === true) { + const latestBlockHash = this.chain.blocks.latest?.hash() + if ( + latestBlockHash !== undefined && + equalsBytes(latestBlockHash, block.header.parentHash) === true + ) { // If new block is child of current chain tip, insert new block into chain await this.chain.putBlocks([block]) // Check if new sync target height can be set @@ -350,10 +355,10 @@ export class FullSynchronizer extends Synchronizer { * Chain was updated, new block hashes received * @param data new block hash announcements */ - handleNewBlockHashes(data: [Buffer, bigint][]) { + handleNewBlockHashes(data: [Uint8Array, bigint][]) { if (!data.length || !this.fetcher || this.fetcher.syncErrored) return let min = BigInt(-1) - let newSyncHeight: [Buffer, bigint] | undefined + let newSyncHeight: [Uint8Array, bigint] | undefined const blockNumberList: bigint[] = [] for (const value of data) { const blockNumber = value[1] @@ -392,7 +397,7 @@ export class FullSynchronizer extends Synchronizer { this.config.syncTargetHeight !== BigInt(0) && this.chain.blocks.height <= this.config.syncTargetHeight - BigInt(50) this.execution.run(true, shouldRunOnlyBatched).catch((e) => { - this.config.logger.error(`Full sync execution trigger erored`, {}, e) + this.config.logger.error(`Full sync execution trigger errored`, {}, e) }) } diff --git a/packages/client/lib/sync/skeleton.ts b/packages/client/lib/sync/skeleton.ts index 34589ca4f4..94a7060d0f 100644 --- a/packages/client/lib/sync/skeleton.ts +++ b/packages/client/lib/sync/skeleton.ts @@ -3,11 +3,12 @@ import { Hardfork } from '@ethereumjs/common' import { RLP } from '@ethereumjs/rlp' import { Lock, - arrToBufArr, - bigIntToBuffer, - bufferToBigInt, - bufferToInt, - intToBuffer, + bigIntToBytes, + bytesToBigInt, + bytesToInt, + equalsBytes, + intToBytes, + utf8ToBytes, zeros, } from '@ethereumjs/util' @@ -44,9 +45,9 @@ type SkeletonProgress = { type SkeletonSubchain = { head: bigint /** Block number of the newest header in the subchain */ tail: bigint /** Block number of the oldest header in the subchain */ - next: Buffer /** Block hash of the next oldest header in the subchain */ + next: Uint8Array /** Block hash of the next oldest header in the subchain */ } -type SkeletonSubchainRLP = [head: Buffer, tail: Buffer, next: Buffer] +type SkeletonSubchainRLP = [head: Uint8Array, tail: Uint8Array, next: Uint8Array] /** * errSyncReorged is an internal helper error to signal that the head chain of @@ -134,7 +135,7 @@ export class Skeleton extends MetaDBManager { if (tail === BigInt(0)) return true if (tail <= this.chain.blocks.height + BigInt(1)) { const nextBlock = await this.chain.getBlock(tail - BigInt(1)) - const linked = next.equals(nextBlock.hash()) + const linked = equalsBytes(next, nextBlock.hash()) if (linked && this.status.progress.subchains.length > 1) { // Remove all other subchains as no more relevant const junkedSubChains = this.status.progress.subchains.splice(1) @@ -170,7 +171,7 @@ export class Skeleton extends MetaDBManager { for (let newHead = head + BigInt(1); newHead <= target; newHead += BigInt(1)) { const newBlock = await this.getBlock(newHead, true) - if (newBlock === undefined || !newBlock.header.parentHash.equals(headBlock.hash())) { + if (newBlock === undefined || !equalsBytes(newBlock.header.parentHash, headBlock.hash())) { // Head can't be updated forward break } @@ -195,7 +196,7 @@ export class Skeleton extends MetaDBManager { // the outer loop to tear down the skeleton sync and restart it const { number } = head.header if (number === BigInt(0)) { - if (!this.chain.genesis.hash().equals(head.hash())) { + if (!equalsBytes(this.chain.genesis.hash(), head.hash())) { throw Error( `Invalid genesis setHead announcement number=${number} hash=${short( head.hash() @@ -234,7 +235,7 @@ export class Skeleton extends MetaDBManager { // Check if its duplicate announcement, if not trim the head and let the match run // post this if block const mayBeDupBlock = await this.getBlock(number) - if (mayBeDupBlock !== undefined && mayBeDupBlock.header.hash().equals(head.hash())) { + if (mayBeDupBlock !== undefined && equalsBytes(mayBeDupBlock.header.hash(), head.hash())) { this.config.logger.debug( `Skeleton duplicate announcement tail=${lastchain.tail} head=${ lastchain.head @@ -277,7 +278,7 @@ export class Skeleton extends MetaDBManager { } } const parent = await this.getBlock(number - BigInt(1)) - if (!parent || !parent.hash().equals(head.header.parentHash)) { + if (parent === undefined || !equalsBytes(parent.hash(), head.header.parentHash)) { if (force) { this.config.logger.warn( `Beacon chain forked ancestor=${parent?.header.number} hash=${short( @@ -329,7 +330,7 @@ export class Skeleton extends MetaDBManager { if ( subchain === undefined || parent === undefined || - !parent.hash().equals(head.header.parentHash) + !equalsBytes(parent.hash(), head.header.parentHash) ) { const s = { head: head.header.number, @@ -425,10 +426,11 @@ export class Skeleton extends MetaDBManager { } // If the old subchain is an extension of the new one, merge the two // and let the skeleton syncer restart (to clean internal state) + + const subChain1Head = await this.getBlock(this.status.progress.subchains[1].head) if ( - (await this.getBlock(this.status.progress.subchains[1].head)) - ?.hash() - .equals(this.status.progress.subchains[0].next) === true + subChain1Head !== undefined && + equalsBytes(subChain1Head.hash(), this.status.progress.subchains[0].next) === true ) { // only merge is we can integrate a big progress, as each merge leads // to disruption of the block fetcher to start a fresh @@ -482,7 +484,7 @@ export class Skeleton extends MetaDBManager { // from previous events especially if the previous subchains merge continue } else if (number === BigInt(0)) { - if (!this.chain.genesis.hash().equals(block.hash())) { + if (!equalsBytes(this.chain.genesis.hash(), block.hash())) { throw Error( `Skeleton pubBlocks with invalid genesis block number=${number} hash=${short( block.hash() @@ -495,7 +497,7 @@ export class Skeleton extends MetaDBManager { } // Extend subchain or create new segment if necessary - if (this.status.progress.subchains[0].next.equals(block.hash())) { + if (equalsBytes(this.status.progress.subchains[0].next, block.hash())) { await this.putBlock(block) this.pulled += BigInt(1) this.status.progress.subchains[0].tail = block.header.number @@ -573,13 +575,13 @@ export class Skeleton extends MetaDBManager { do { newTail = newTail + BigInt(this.config.skeletonFillCanonicalBackStep) tailBlock = await this.getBlock(newTail, true) - } while (!tailBlock && newTail <= head) + } while (tailBlock === undefined && newTail <= head) if (newTail > head) { newTail = head tailBlock = await this.getBlock(newTail, true) } - if (tailBlock && newTail) { + if (tailBlock !== undefined && newTail) { this.config.logger.info(`Backstepped skeleton head=${head} tail=${newTail}`) this.status.progress.subchains[0].tail = tailBlock.header.number this.status.progress.subchains[0].next = tailBlock.header.parentHash @@ -637,7 +639,7 @@ export class Skeleton extends MetaDBManager { // Get next block const number = canonicalHead + BigInt(1) const block = await this.getBlock(number) - if (!block) { + if (block === undefined) { // This shouldn't happen, but if it does because of some issues, we should back step // and fetch again this.config.logger.debug( @@ -714,13 +716,19 @@ export class Skeleton extends MetaDBManager { ) } - serialize({ hardfork, blockRLP }: { hardfork: Hardfork | string; blockRLP: Buffer }): Buffer { - const skeletonArr = [Buffer.from(hardfork), blockRLP] - return Buffer.from(RLP.encode(skeletonArr)) + serialize({ + hardfork, + blockRLP, + }: { + hardfork: Hardfork | string + blockRLP: Uint8Array + }): Uint8Array { + const skeletonArr = [utf8ToBytes(hardfork), blockRLP] + return RLP.encode(skeletonArr) } - deserialize(rlp: Buffer): { hardfork: Hardfork | string; blockRLP: Buffer } { - const [hardfork, blockRLP] = arrToBufArr(RLP.decode(Uint8Array.from(rlp))) as Buffer[] + deserialize(rlp: Uint8Array): { hardfork: Hardfork | string; blockRLP: Uint8Array } { + const [hardfork, blockRLP] = RLP.decode(rlp) as Uint8Array[] return { hardfork: hardfork.toString(), blockRLP } } @@ -730,11 +738,11 @@ export class Skeleton extends MetaDBManager { private async putBlock(block: Block): Promise { // Serialize the block with its hardfork so that its easy to load the block latter const rlp = this.serialize({ hardfork: block._common.hardfork(), blockRLP: block.serialize() }) - await this.put(DBKey.SkeletonBlock, bigIntToBuffer(block.header.number), rlp) + await this.put(DBKey.SkeletonBlock, bigIntToBytes(block.header.number), rlp) await this.put( DBKey.SkeletonBlockHashToNumber, block.hash(), - bigIntToBuffer(block.header.number) + bigIntToBytes(block.header.number) ) return true } @@ -744,7 +752,7 @@ export class Skeleton extends MetaDBManager { */ async getBlock(number: bigint, onlySkeleton = false): Promise { try { - const rlp = await this.get(DBKey.SkeletonBlock, bigIntToBuffer(number)) + const rlp = await this.get(DBKey.SkeletonBlock, bigIntToBytes(number)) const { hardfork, blockRLP } = this.deserialize(rlp!) const common = this.config.chainCommon.copy() common.setHardfork(hardfork) @@ -768,10 +776,10 @@ export class Skeleton extends MetaDBManager { /** * Gets a skeleton block from the db by hash */ - async getBlockByHash(hash: Buffer, onlySkeleton?: boolean): Promise { + async getBlockByHash(hash: Uint8Array, onlySkeleton?: boolean): Promise { const number = await this.get(DBKey.SkeletonBlockHashToNumber, hash) if (number) { - return this.getBlock(bufferToBigInt(number), onlySkeleton) + return this.getBlock(bytesToBigInt(number), onlySkeleton) } else { if (onlySkeleton === true || !this.status.linked) { return undefined @@ -790,7 +798,7 @@ export class Skeleton extends MetaDBManager { */ async deleteBlock(block: Block): Promise { try { - await this.delete(DBKey.SkeletonBlock, bigIntToBuffer(block.header.number)) + await this.delete(DBKey.SkeletonBlock, bigIntToBytes(block.header.number)) await this.delete(DBKey.SkeletonBlockHashToNumber, block.hash()) return true } catch (error: any) { @@ -814,7 +822,7 @@ export class Skeleton extends MetaDBManager { private async writeSyncStatus(): Promise { this.logSyncStatus('Writing') const encodedStatus = this.statusToRLP() - await this.put(DBKey.SkeletonStatus, Buffer.alloc(0), encodedStatus) + await this.put(DBKey.SkeletonStatus, new Uint8Array(0), encodedStatus) return true } @@ -822,7 +830,7 @@ export class Skeleton extends MetaDBManager { * Reads the {@link SkeletonStatus} from db */ private async getSyncStatus(): Promise { - const rawStatus = await this.get(DBKey.SkeletonStatus, Buffer.alloc(0)) + const rawStatus = await this.get(DBKey.SkeletonStatus, new Uint8Array(0)) if (!rawStatus) return const status = this.statusRLPtoObject(rawStatus) this.status = status @@ -832,27 +840,25 @@ export class Skeleton extends MetaDBManager { /** * Encodes a {@link SkeletonStatus} to RLP for saving to the db */ - private statusToRLP(): Buffer { + private statusToRLP(): Uint8Array { const subchains: SkeletonSubchainRLP[] = this.status.progress.subchains.map((subchain) => [ - bigIntToBuffer(subchain.head), - bigIntToBuffer(subchain.tail), + bigIntToBytes(subchain.head), + bigIntToBytes(subchain.tail), subchain.next, ]) - return Buffer.from( - RLP.encode([ - subchains, - // linked - intToBuffer(this.status.linked ? 1 : 0), - // canonocalHeadReset - intToBuffer(this.status.canonicalHeadReset ? 1 : 0), - ]) - ) + return RLP.encode([ + subchains, + // linked + intToBytes(this.status.linked ? 1 : 0), + // canonocalHeadReset + intToBytes(this.status.canonicalHeadReset ? 1 : 0), + ]) } /** * Decodes an RLP encoded {@link SkeletonStatus} */ - private statusRLPtoObject(serializedStatus: Buffer): SkeletonStatus { + private statusRLPtoObject(serializedStatus: Uint8Array): SkeletonStatus { const status: SkeletonStatus = { progress: { subchains: [] }, linked: false, @@ -860,17 +866,17 @@ export class Skeleton extends MetaDBManager { } const rawStatus = RLP.decode(serializedStatus) as unknown as [ SkeletonSubchainRLP[], - Buffer, - Buffer + Uint8Array, + Uint8Array ] const subchains: SkeletonSubchain[] = rawStatus[0].map((raw) => ({ - head: bufferToBigInt(raw[0]), - tail: bufferToBigInt(raw[1]), + head: bytesToBigInt(raw[0]), + tail: bytesToBigInt(raw[1]), next: raw[2], })) status.progress.subchains = subchains - status.linked = bufferToInt(rawStatus[1]) === 1 - status.canonicalHeadReset = bufferToInt(rawStatus[2]) === 1 + status.linked = bytesToInt(rawStatus[1]) === 1 + status.canonicalHeadReset = bytesToInt(rawStatus[2]) === 1 return status } } diff --git a/packages/client/lib/sync/snapsync.ts b/packages/client/lib/sync/snapsync.ts index 845e44ce71..b0b2cd7118 100644 --- a/packages/client/lib/sync/snapsync.ts +++ b/packages/client/lib/sync/snapsync.ts @@ -1,4 +1,5 @@ import { DefaultStateManager } from '@ethereumjs/statemanager' +import { bytesToHex } from '@ethereumjs/util' import { Event } from '../types' @@ -123,9 +124,7 @@ export class SnapSynchronizer extends Synchronizer { // eslint-disable-next-line eqeqeq if (this.config.syncTargetHeight == null || this.config.syncTargetHeight < latest.number) { this.config.syncTargetHeight = height - this.config.logger.info( - `New sync target height=${height} hash=${latest.hash().toString('hex')}` - ) + this.config.logger.info(`New sync target height=${height} hash=${bytesToHex(latest.hash())}`) } // For convenient testing diff --git a/packages/client/lib/types.ts b/packages/client/lib/types.ts index bf56c3c84f..051d16b7d8 100644 --- a/packages/client/lib/types.ts +++ b/packages/client/lib/types.ts @@ -86,7 +86,7 @@ export type EventBusType = EventBus & /** * Like types */ -export type Key = Buffer +export type Key = Uint8Array export type KeyLike = string | Key export type MultiaddrLike = string | string[] | Multiaddr | Multiaddr[] diff --git a/packages/client/lib/util/debug.ts b/packages/client/lib/util/debug.ts index 6428cc5772..00d9702ed3 100644 --- a/packages/client/lib/util/debug.ts +++ b/packages/client/lib/util/debug.ts @@ -1,3 +1,5 @@ +import { bytesToHex } from 'ethereum-cryptography/utils' + import { DataDirectory } from '..' import type { VMExecution } from '../execution' @@ -35,17 +37,17 @@ const main = async () => { const common = new Common({ chain: '${execution.config.execCommon.chainName()}', hardfork: '${ execution.hardfork }' }) - const block = Block.fromRLPSerializedBlock(Buffer.from('${block - .serialize() - .toString('hex')}', 'hex'), { common }) + const block = Block.fromRLPSerializedBlock(hexStringToBytes('${bytesToHex( + block.serialize() + )}'), { common }) const stateDB = new Level('${execution.config.getDataDirectory(DataDirectory.State)}') const trie = new Trie({ db: stateDB, useKeyHashing: true }) const stateManager = new DefaultStateManager({ trie, common }) // Ensure we run on the right root - stateManager.setStateRoot(Buffer.from('${( + stateManager.setStateRoot(hexStringToBytes('${bytesToHex( await execution.vm.stateManager.getStateRoot() - ).toString('hex')}', 'hex')) + )}')) const chainDB = new Level('${execution.config.getDataDirectory(DataDirectory.Chain)}') diff --git a/packages/client/lib/util/index.ts b/packages/client/lib/util/index.ts index f537c87f49..755880a66b 100644 --- a/packages/client/lib/util/index.ts +++ b/packages/client/lib/util/index.ts @@ -1,6 +1,7 @@ /** * @module util */ +import { bytesToPrefixedHexString } from '@ethereumjs/util' import { platform } from 'os' import { version as packageVersion } from '../../package.json' @@ -8,12 +9,12 @@ import { version as packageVersion } from '../../package.json' export * from './parse' export * from './rpc' -export function short(buf: Buffer | string): string { - if (buf === null || buf === undefined || buf === '') return '' - const bufStr = Buffer.isBuffer(buf) ? `0x${buf.toString('hex')}` : buf - let str = bufStr.substring(0, 6) + '…' - if (bufStr.length === 66) { - str += bufStr.substring(62) +export function short(bytes: Uint8Array | string): string { + if (bytes === null || bytes === undefined || bytes === '') return '' + const bytesString = bytes instanceof Uint8Array ? bytesToPrefixedHexString(bytes) : bytes + let str = bytesString.substring(0, 6) + '…' + if (bytesString.length === 66) { + str += bytesString.substring(62) } return str } diff --git a/packages/client/lib/util/metaDBManager.ts b/packages/client/lib/util/metaDBManager.ts index c56251acd5..c20feb68bd 100644 --- a/packages/client/lib/util/metaDBManager.ts +++ b/packages/client/lib/util/metaDBManager.ts @@ -1,4 +1,4 @@ -import { intToBuffer } from '@ethereumjs/util' +import { concatBytes, intToBytes } from '@ethereumjs/util' import type { Chain } from '../blockchain' import type { Config } from '../config' @@ -29,7 +29,7 @@ export interface MetaDBManagerOptions { config: Config /* Meta database (receipts, logs, indexes) */ - metaDB: AbstractLevel + metaDB: AbstractLevel } /** @@ -38,7 +38,7 @@ export interface MetaDBManagerOptions { export class MetaDBManager { protected chain: Chain protected config: Config - private metaDB: AbstractLevel + private metaDB: AbstractLevel constructor(options: MetaDBManagerOptions) { this.chain = options.chain @@ -46,15 +46,15 @@ export class MetaDBManager { this.metaDB = options.metaDB } - private dbKey(type: DBKey, key: Buffer) { - return Buffer.concat([intToBuffer(type), key]) + private dbKey(type: DBKey, key: Uint8Array) { + return concatBytes(intToBytes(type), key) } - async put(type: DBKey, hash: Buffer, value: Buffer) { + async put(type: DBKey, hash: Uint8Array, value: Uint8Array) { await this.metaDB.put(this.dbKey(type, hash), value, encodingOpts) } - async get(type: DBKey, hash: Buffer): Promise { + async get(type: DBKey, hash: Uint8Array): Promise { try { return await this.metaDB.get(this.dbKey(type, hash), encodingOpts) } catch (error: any) { @@ -65,7 +65,7 @@ export class MetaDBManager { } } - async delete(type: DBKey, hash: Buffer) { + async delete(type: DBKey, hash: Uint8Array) { await this.metaDB.del(this.dbKey(type, hash), encodingOpts) } } diff --git a/packages/client/lib/util/parse.ts b/packages/client/lib/util/parse.ts index 8916168bdd..5694dcf97f 100644 --- a/packages/client/lib/util/parse.ts +++ b/packages/client/lib/util/parse.ts @@ -1,3 +1,4 @@ +import { hexStringToBytes } from '@ethereumjs/util' import { Multiaddr, multiaddr } from 'multiaddr' import { URL } from 'url' @@ -83,12 +84,9 @@ export function parseTransports(transports: string[]) { } /** - * Returns Buffer from input hexadecimal string or Buffer - * @param input hexadecimal string or Buffer + * Returns Uint8Array from input hexadecimal string or Uint8Array + * @param input hexadecimal string or Uint8Array */ -export function parseKey(input: string | Buffer) { - if (Buffer.isBuffer(input)) { - return input - } - return Buffer.from(input, 'hex') +export function parseKey(input: string | Uint8Array): Uint8Array { + return input instanceof Uint8Array ? input : hexStringToBytes(input) } diff --git a/packages/client/lib/util/rpc.ts b/packages/client/lib/util/rpc.ts index e029ffc793..54216b8c9b 100644 --- a/packages/client/lib/util/rpc.ts +++ b/packages/client/lib/util/rpc.ts @@ -30,7 +30,7 @@ type CreateRPCServerListenerOpts = { withEngineMiddleware?: WithEngineMiddleware } type CreateWSServerOpts = CreateRPCServerListenerOpts & { httpServer?: HttpServer } -type WithEngineMiddleware = { jwtSecret: Buffer; unlessFn?: (req: IncomingMessage) => boolean } +type WithEngineMiddleware = { jwtSecret: Uint8Array; unlessFn?: (req: IncomingMessage) => boolean } export enum MethodConfig { WithEngine = 'withengine', @@ -150,7 +150,7 @@ export function createRPCServer( return { server, methods, namespaces } } -function checkHeaderAuth(req: any, jwtSecret: Buffer): void { +function checkHeaderAuth(req: any, jwtSecret: Uint8Array): void { const header = (req.headers['Authorization'] ?? req.headers['authorization']) as string if (!header) throw Error(`Missing auth header`) const token = header.trim().split(' ')[1] diff --git a/packages/client/test/blockchain/chain.spec.ts b/packages/client/test/blockchain/chain.spec.ts index 20283a089e..e5a388f9db 100644 --- a/packages/client/test/blockchain/chain.spec.ts +++ b/packages/client/test/blockchain/chain.spec.ts @@ -2,7 +2,7 @@ // needed for karma-typescript bundling import { Block } from '@ethereumjs/block' import { Blockchain } from '@ethereumjs/blockchain' -import { Buffer } from 'buffer' // eslint-disable-line @typescript-eslint/no-unused-vars +import { bytesToHex, equalsBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' import * as util from 'util' // eslint-disable-line @typescript-eslint/no-unused-vars @@ -34,11 +34,11 @@ tape('[Chain]', (t) => { t.equal(chain.blocks.td.toString(10), '17179869184', 'get chain.blocks.td') t.equal(chain.blocks.height.toString(10), '0', 'get chain.blocks.height') t.equal( - chain.genesis.hash().toString('hex'), + bytesToHex(chain.genesis.hash()), 'd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3', 'get chain.genesis' ) - t.ok(chain.genesis.hash().equals(chain.blocks.latest!.hash()), 'get chain.block.latest') + t.ok(equalsBytes(chain.genesis.hash(), chain.blocks.latest!.hash()), 'get chain.block.latest') await chain.close() t.end() }) diff --git a/packages/client/test/integration/fullethereumservice.spec.ts b/packages/client/test/integration/fullethereumservice.spec.ts index d9e11e4dce..3f2996085a 100644 --- a/packages/client/test/integration/fullethereumservice.spec.ts +++ b/packages/client/test/integration/fullethereumservice.spec.ts @@ -3,7 +3,7 @@ import { Blockchain } from '@ethereumjs/blockchain' import { Hardfork } from '@ethereumjs/common' import { DefaultStateManager } from '@ethereumjs/statemanager' import { FeeMarketEIP1559Transaction } from '@ethereumjs/tx' -import { Account, toBuffer } from '@ethereumjs/util' +import { Account, bytesToHex, equalsBytes, hexStringToBytes, toBytes } from '@ethereumjs/util' import * as tape from 'tape' import * as td from 'testdouble' @@ -51,12 +51,11 @@ tape('[Integration:FullEthereumService]', async (t) => { const [server, service] = await setup() const peer = await server.accept('peer0') const [reqId1, headers] = await peer.eth!.getBlockHeaders({ block: BigInt(1), max: 2 }) - const hash = Buffer.from( - 'a321d27cd2743617c1c1b0d7ecb607dd14febcdfca8f01b79c3f0249505ea069', - 'hex' + const hash = hexStringToBytes( + 'a321d27cd2743617c1c1b0d7ecb607dd14febcdfca8f01b79c3f0249505ea069' ) t.equal(reqId1, BigInt(1), 'handled GetBlockHeaders') - t.ok(headers![1].hash().equals(hash), 'handled GetBlockHeaders') + t.ok(equalsBytes(headers![1].hash(), hash), 'handled GetBlockHeaders') const res = await peer.eth!.getBlockBodies({ hashes: [hash] }) const [reqId2, bodies] = res t.equal(reqId2, BigInt(2), 'handled GetBlockBodies') @@ -89,7 +88,7 @@ tape('[Integration:FullEthereumService]', async (t) => { const txData = '0x02f901100180843b9aca00843b9aca008402625a0094cccccccccccccccccccccccccccccccccccccccc830186a0b8441a8451e600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f85bf859940000000000000000000000000000000000000101f842a00000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000060a701a0afb6e247b1c490e284053c87ab5f6b59e219d51f743f7a4d83e400782bc7e4b9a0479a268e0e0acd4de3f1e28e4fac2a6b32a4195e8dfa9d19147abe8807aa6f64' - const tx = FeeMarketEIP1559Transaction.fromSerializedTx(toBuffer(txData)) + const tx = FeeMarketEIP1559Transaction.fromSerializedTx(toBytes(txData)) await service.execution.vm.stateManager.putAccount( tx.getSenderAddress(), new Account(BigInt(0), BigInt('40000000000100000')) @@ -114,11 +113,7 @@ tape('[Integration:FullEthereumService]', async (t) => { Hardfork.London ) const [_, txs] = await peer.eth!.getPooledTransactions({ hashes: [tx.hash()] }) - t.equal( - txs[0].hash().toString('hex'), - tx.hash().toString('hex'), - 'handled GetPooledTransactions' - ) + t.ok(equalsBytes(txs[0].hash(), tx.hash()), 'handled GetPooledTransactions') peer.eth!.send('Transactions', [tx]) t.pass('handled Transactions') @@ -129,7 +124,7 @@ tape('[Integration:FullEthereumService]', async (t) => { const peer = await server.accept('peer0') const { headers } = await peer.les!.getBlockHeaders({ block: BigInt(1), max: 2 }) t.equals( - headers[1].hash().toString('hex'), + bytesToHex(headers[1].hash()), 'a321d27cd2743617c1c1b0d7ecb607dd14febcdfca8f01b79c3f0249505ea069', 'handled GetBlockHeaders' ) diff --git a/packages/client/test/integration/merge.spec.ts b/packages/client/test/integration/merge.spec.ts index a2febee35a..68722a4dee 100644 --- a/packages/client/test/integration/merge.spec.ts +++ b/packages/client/test/integration/merge.spec.ts @@ -7,7 +7,7 @@ import { ConsensusType, Hardfork, } from '@ethereumjs/common' -import { Address } from '@ethereumjs/util' +import { Address, hexStringToBytes } from '@ethereumjs/util' import * as tape from 'tape' import { Chain } from '../../lib/blockchain' @@ -65,10 +65,10 @@ tape('[Integration:Merge]', async (t) => { }, { baseChain: ChainCommon.Ropsten, hardfork: Hardfork.London } ) - const accounts: [Address, Buffer][] = [ + const accounts: [Address, Uint8Array][] = [ [ - new Address(Buffer.from('0b90087d864e82a284dca15923f3776de6bb016f', 'hex')), - Buffer.from('64bf9cc30328b0e42387b3c82c614e6386259136235e20c1357bd11cdee86993', 'hex'), + new Address(hexStringToBytes('0b90087d864e82a284dca15923f3776de6bb016f')), + hexStringToBytes('64bf9cc30328b0e42387b3c82c614e6386259136235e20c1357bd11cdee86993'), ], ] async function minerSetup(common: Common): Promise<[MockServer, FullEthereumService]> { diff --git a/packages/client/test/integration/miner.spec.ts b/packages/client/test/integration/miner.spec.ts index 372fedf55c..7bd5f11896 100644 --- a/packages/client/test/integration/miner.spec.ts +++ b/packages/client/test/integration/miner.spec.ts @@ -6,7 +6,7 @@ import { ConsensusType, Hardfork, } from '@ethereumjs/common' -import { Address } from '@ethereumjs/util' +import { Address, hexStringToBytes } from '@ethereumjs/util' import * as tape from 'tape' import { Chain } from '../../lib/blockchain' @@ -42,10 +42,10 @@ tape('[Integration:Miner]', async (t) => { }, { baseChain: ChainCommon.Goerli, hardfork: Hardfork.London } ) - const accounts: [Address, Buffer][] = [ + const accounts: [Address, Uint8Array][] = [ [ - new Address(Buffer.from('0b90087d864e82a284dca15923f3776de6bb016f', 'hex')), - Buffer.from('64bf9cc30328b0e42387b3c82c614e6386259136235e20c1357bd11cdee86993', 'hex'), + new Address(hexStringToBytes('0b90087d864e82a284dca15923f3776de6bb016f')), + hexStringToBytes('64bf9cc30328b0e42387b3c82c614e6386259136235e20c1357bd11cdee86993'), ], ] async function minerSetup(): Promise<[MockServer, FullEthereumService]> { diff --git a/packages/client/test/integration/mocks/mockpeer.ts b/packages/client/test/integration/mocks/mockpeer.ts index 82d35a6b49..5cea1159b9 100644 --- a/packages/client/test/integration/mocks/mockpeer.ts +++ b/packages/client/test/integration/mocks/mockpeer.ts @@ -14,7 +14,7 @@ import type { RemoteStream } from './network' // TypeScript doesn't have support yet for ReturnType // with generic types, so this wrapper is used as a helper. -const wrapperPushable = () => pushable() +const wrapperPushable = () => pushable() export type Pushable = ReturnType interface MockPeerOptions extends PeerOptions { diff --git a/packages/client/test/miner/miner.spec.ts b/packages/client/test/miner/miner.spec.ts index 2c2ba5c7ae..1c24e89bfe 100644 --- a/packages/client/test/miner/miner.spec.ts +++ b/packages/client/test/miner/miner.spec.ts @@ -2,7 +2,7 @@ import { Block, BlockHeader } from '@ethereumjs/block' import { Common, Chain as CommonChain, Hardfork } from '@ethereumjs/common' import { DefaultStateManager } from '@ethereumjs/statemanager' import { FeeMarketEIP1559Transaction, Transaction } from '@ethereumjs/tx' -import { Address } from '@ethereumjs/util' +import { Address, equalsBytes, hexStringToBytes } from '@ethereumjs/util' import { VmState } from '@ethereumjs/vm/dist/eei/vmState' import { AbstractLevel } from 'abstract-level' import { keccak256 } from 'ethereum-cryptography/keccak' @@ -21,19 +21,13 @@ import type { CliqueConsensus } from '@ethereumjs/blockchain' import type { VM } from '@ethereumjs/vm' const A = { - address: new Address(Buffer.from('0b90087d864e82a284dca15923f3776de6bb016f', 'hex')), - privateKey: Buffer.from( - '64bf9cc30328b0e42387b3c82c614e6386259136235e20c1357bd11cdee86993', - 'hex' - ), + address: new Address(hexStringToBytes('0b90087d864e82a284dca15923f3776de6bb016f')), + privateKey: hexStringToBytes('64bf9cc30328b0e42387b3c82c614e6386259136235e20c1357bd11cdee86993'), } const B = { - address: new Address(Buffer.from('6f62d8382bf2587361db73ceca28be91b2acb6df', 'hex')), - privateKey: Buffer.from( - '2a6e9ad5a6a8e4f17149b8bc7128bf090566a11dbd63c30e5a0ee9f161309cd6', - 'hex' - ), + address: new Address(hexStringToBytes('6f62d8382bf2587361db73ceca28be91b2acb6df')), + privateKey: hexStringToBytes('2a6e9ad5a6a8e4f17149b8bc7128bf090566a11dbd63c30e5a0ee9f161309cd6'), } const setBalance = async (vm: VM, address: Address, balance: bigint) => { @@ -95,7 +89,7 @@ tape('[Miner]', async (t) => { const common = new Common({ chain: CommonChain.Rinkeby, hardfork: Hardfork.Berlin }) common.setMaxListeners(50) - const accounts: [Address, Buffer][] = [[A.address, A.privateKey]] + const accounts: [Address, Uint8Array][] = [[A.address, A.privateKey]] const config = new Config({ transports: [], accounts, mine: true, common }) config.events.setMaxListeners(50) @@ -263,7 +257,8 @@ tape('[Miner]', async (t) => { const msg = 'txs in block should be properly ordered by gasPrice and nonce' const expectedOrder = [txB01, txA01, txA02, txA03] for (const [index, tx] of expectedOrder.entries()) { - t.ok(blocks[0].transactions[index]?.hash().equals(tx.hash()), msg) + const txHash = blocks[0].transactions[index]?.hash() + t.ok(txHash !== undefined && equalsBytes(txHash, tx.hash()), msg) } miner.stop() txPool.stop() @@ -307,7 +302,8 @@ tape('[Miner]', async (t) => { const msg = 'txs in block should be properly ordered by gasPrice and nonce' const expectedOrder = [txB01, txA01, txA02, txA03] for (const [index, tx] of expectedOrder.entries()) { - t.ok(blocks[0].transactions[index]?.hash().equals(tx.hash()), msg) + const txHash = blocks[0].transactions[index]?.hash() + t.ok(txHash !== undefined && equalsBytes(txHash, tx.hash()), msg) } miner.stop() txPool.stop() @@ -452,7 +448,7 @@ tape('[Miner]', async (t) => { await setBalance(vm, A.address, BigInt('200000000000001')) // add many txs to slow assembling - let privateKey = Buffer.from(keccak256(Buffer.from(''))) + let privateKey = keccak256(new Uint8Array(0)) for (let i = 0; i < 1000; i++) { // In order not to pollute TxPool with too many txs from the same address // (or txs which are already known), keep generating a new address for each tx @@ -460,7 +456,7 @@ tape('[Miner]', async (t) => { await setBalance(vm, address, BigInt('200000000000001')) const tx = createTx({ address, privateKey }) await txPool.add(tx) - privateKey = Buffer.from(keccak256(privateKey)) + privateKey = keccak256(privateKey) } chain.putBlocks = () => { diff --git a/packages/client/test/miner/pendingBlock.spec.ts b/packages/client/test/miner/pendingBlock.spec.ts index 47ef4efb24..cc8f56e820 100644 --- a/packages/client/test/miner/pendingBlock.spec.ts +++ b/packages/client/test/miner/pendingBlock.spec.ts @@ -6,11 +6,18 @@ import { commitmentsToVersionedHashes, getBlobs, } from '@ethereumjs/tx/dist/utils/blobHelpers' -import { Account, Address, bufferToHex } from '@ethereumjs/util' +import { + Account, + Address, + bytesToHex, + bytesToPrefixedHexString, + equalsBytes, + hexStringToBytes, + randomBytes, +} from '@ethereumjs/util' import { VM } from '@ethereumjs/vm' import { VmState } from '@ethereumjs/vm/dist/eei/vmState' import * as kzg from 'c-kzg' -import { randomBytes } from 'crypto' import * as tape from 'tape' import * as td from 'testdouble' @@ -23,19 +30,13 @@ import { mockBlockchain } from '../rpc/mockBlockchain' import type { TypedTransaction } from '@ethereumjs/tx' const A = { - address: new Address(Buffer.from('0b90087d864e82a284dca15923f3776de6bb016f', 'hex')), - privateKey: Buffer.from( - '64bf9cc30328b0e42387b3c82c614e6386259136235e20c1357bd11cdee86993', - 'hex' - ), + address: new Address(hexStringToBytes('0b90087d864e82a284dca15923f3776de6bb016f')), + privateKey: hexStringToBytes('64bf9cc30328b0e42387b3c82c614e6386259136235e20c1357bd11cdee86993'), } const B = { - address: new Address(Buffer.from('6f62d8382bf2587361db73ceca28be91b2acb6df', 'hex')), - privateKey: Buffer.from( - '2a6e9ad5a6a8e4f17149b8bc7128bf090566a11dbd63c30e5a0ee9f161309cd6', - 'hex' - ), + address: new Address(hexStringToBytes('6f62d8382bf2587361db73ceca28be91b2acb6df')), + privateKey: hexStringToBytes('2a6e9ad5a6a8e4f17149b8bc7128bf090566a11dbd63c30e5a0ee9f161309cd6'), } const setBalance = async (vm: VM, address: Address, balance: bigint) => { @@ -144,10 +145,10 @@ tape('[PendingBlock]', async (t) => { const parentBlock = await vm.blockchain.getCanonicalHeadBlock!() const payloadId = await pendingBlock.start(vm, parentBlock) t.equal(pendingBlock.pendingPayloads.size, 1, 'should set the pending payload') - const payload = pendingBlock.pendingPayloads.get(bufferToHex(payloadId)) + const payload = pendingBlock.pendingPayloads.get(bytesToPrefixedHexString(payloadId)) t.equal( (payload as any).transactions.filter( - (tx: TypedTransaction) => bufferToHex(tx.hash()) === bufferToHex(txA011.hash()) + (tx: TypedTransaction) => bytesToHex(tx.hash()) === bytesToHex(txA011.hash()) ).length, 1, 'txA011 should be in block' @@ -163,7 +164,7 @@ tape('[PendingBlock]', async (t) => { t.equal(block?.transactions.length, 2, 'should include txs from pool') t.equal( (payload as any).transactions.filter( - (tx: TypedTransaction) => bufferToHex(tx.hash()) === bufferToHex(txB011.hash()) + (tx: TypedTransaction) => bytesToHex(tx.hash()) === bytesToHex(txB011.hash()) ).length, 1, 'txB011 should be in block' @@ -274,11 +275,9 @@ tape('[PendingBlock]', async (t) => { const commitments = blobsToCommitments(blobs) const versionedHashes = commitmentsToVersionedHashes(commitments) - const bufferedHashes = versionedHashes.map((el) => Buffer.from(el)) - const txA01 = BlobEIP4844Transaction.fromTxData( { - versionedHashes: bufferedHashes, + versionedHashes, blobs, kzgCommitments: commitments, maxFeePerDataGas: 100000000n, @@ -296,7 +295,8 @@ tape('[PendingBlock]', async (t) => { const parentBlock = await vm.blockchain.getCanonicalHeadBlock!() const payloadId = await pendingBlock.start(vm, parentBlock) await pendingBlock.build(payloadId) - st.ok(pendingBlock.blobBundles.get(bufferToHex(payloadId))?.blobs[0].equals(blobs[0])) + const pendingBlob = pendingBlock.blobBundles.get(bytesToPrefixedHexString(payloadId))?.blobs[0] + st.ok(pendingBlob !== undefined && equalsBytes(pendingBlob, blobs[0])) kzg.freeTrustedSetup() st.end() }) diff --git a/packages/client/test/net/protocol/ethprotocol.spec.ts b/packages/client/test/net/protocol/ethprotocol.spec.ts index 813daaf2ad..c66d7fe09f 100644 --- a/packages/client/test/net/protocol/ethprotocol.spec.ts +++ b/packages/client/test/net/protocol/ethprotocol.spec.ts @@ -1,8 +1,7 @@ import { Block } from '@ethereumjs/block' import { Common, Hardfork } from '@ethereumjs/common' import { FeeMarketEIP1559Transaction, TransactionFactory } from '@ethereumjs/tx' -import { bigIntToBuffer, bufferToBigInt } from '@ethereumjs/util' -import { randomBytes } from 'crypto' +import { bigIntToBytes, bytesToBigInt, hexStringToBytes, randomBytes } from '@ethereumjs/util' import * as tape from 'tape' import { Chain } from '../../../lib/blockchain/chain' @@ -55,17 +54,17 @@ tape('[EthProtocol]', (t) => { t.deepEquals( p.encodeStatus(), { - networkId: Buffer.from('01', 'hex'), - td: Buffer.from('64', 'hex'), + networkId: hexStringToBytes('01'), + td: hexStringToBytes('64'), bestHash: '0xaa', genesisHash: '0xbb', - latestBlock: Buffer.from('0a', 'hex'), + latestBlock: hexStringToBytes('0a'), }, 'encode status' ) const status = p.decodeStatus({ networkId: [0x01], - td: Buffer.from('64', 'hex'), + td: hexStringToBytes('64'), bestHash: '0xaa', genesisHash: '0xbb', }) @@ -87,14 +86,14 @@ tape('[EthProtocol]', (t) => { const block = Block.fromBlockData({}, { common: config.chainCommon }) const res = p.decode(p.messages.filter((message) => message.name === 'NewBlock')[0], [ block.raw(), - bigIntToBuffer(td), + bigIntToBytes(td), ]) const res2 = p.encode(p.messages.filter((message) => message.name === 'NewBlock')[0], [ block, td, ]) t.deepEquals(res[0].hash(), block.hash(), 'correctly decoded block') - t.equal(bufferToBigInt(res2[1]), td, 'correctly encoded td') + t.equal(bytesToBigInt(res2[1]), td, 'correctly encoded td') t.end() }) @@ -104,7 +103,7 @@ tape('[EthProtocol]', (t) => { const p = new EthProtocol({ config, chain }) const block = Block.fromBlockData({}) const res = p.decode(p.messages.filter((message) => message.name === 'GetReceipts')[0], [ - BigInt(1), + bigIntToBytes(1n), [block.hash()], ]) const res2 = p.encode(p.messages.filter((message) => message.name === 'GetReceipts')[0], { @@ -112,9 +111,9 @@ tape('[EthProtocol]', (t) => { hashes: [block.hash()], }) t.equal(res.reqId, BigInt(1), 'correctly decoded reqId') - t.ok(res.hashes[0].equals(block.hash()), 'correctly decoded blockHash') - t.equal(bufferToBigInt(res2[0]), BigInt(1), 'correctly encoded reqId') - t.ok(res2[1][0].equals(block.hash()), 'correctly encoded blockHash') + t.deepEquals(res.hashes[0], block.hash(), 'correctly decoded blockHash') + t.equal(bytesToBigInt(res2[0]), BigInt(1), 'correctly encoded reqId') + t.deepEquals(res2[1][0], block.hash(), 'correctly encoded blockHash') t.end() }) @@ -138,7 +137,7 @@ tape('[EthProtocol]', (t) => { reqId: BigInt(1), txs: [tx], }) - t.equal(bufferToBigInt(res[0]), BigInt(1), 'correctly encoded reqId') + t.equal(bytesToBigInt(res[0]), BigInt(1), 'correctly encoded reqId') t.deepEqual(res[1][0], tx.serialize(), 'EIP1559 transaction correctly encoded') t.end() }) @@ -154,15 +153,27 @@ tape('[EthProtocol]', (t) => { { status: 1 as 0 | 1, cumulativeBlockGasUsed: BigInt(100), - bitvector: Buffer.alloc(256), - logs: [[Buffer.alloc(20), [Buffer.alloc(32), Buffer.alloc(32, 1)], Buffer.alloc(10)]], + bitvector: new Uint8Array(256), + logs: [ + [ + new Uint8Array(20), + [new Uint8Array(32), new Uint8Array(32).fill(1)], + new Uint8Array(10), + ], + ], txType: 2, }, { status: 0 as 0 | 1, cumulativeBlockGasUsed: BigInt(1000), - bitvector: Buffer.alloc(256, 1), - logs: [[Buffer.alloc(20, 1), [Buffer.alloc(32, 1), Buffer.alloc(32, 1)], Buffer.alloc(10)]], + bitvector: new Uint8Array(256).fill(1), + logs: [ + [ + new Uint8Array(20).fill(1), + [new Uint8Array(32).fill(1), new Uint8Array(32).fill(1)], + new Uint8Array(10), + ], + ], txType: 0, }, ] @@ -172,15 +183,13 @@ tape('[EthProtocol]', (t) => { reqId: BigInt(1), receipts, }) - t.equal(bufferToBigInt(res[0]), BigInt(1), 'correctly encoded reqId') + t.equal(bytesToBigInt(res[0]), BigInt(1), 'correctly encoded reqId') const expectedSerializedReceipts = [ - Buffer.from( - '02f9016d0164b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f866f864940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a001010101010101010101010101010101010101010101010101010101010101018a00000000000000000000', - 'hex' + hexStringToBytes( + '02f9016d0164b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f866f864940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a001010101010101010101010101010101010101010101010101010101010101018a00000000000000000000' ), - Buffer.from( - 'f9016f808203e8b9010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101f866f864940101010101010101010101010101010101010101f842a00101010101010101010101010101010101010101010101010101010101010101a001010101010101010101010101010101010101010101010101010101010101018a00000000000000000000', - 'hex' + hexStringToBytes( + 'f9016f808203e8b9010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101f866f864940101010101010101010101010101010101010101f842a00101010101010101010101010101010101010101010101010101010101010101a001010101010101010101010101010101010101010101010101010101010101018a00000000000000000000' ), ] t.deepEqual(res[1], expectedSerializedReceipts, 'correctly encoded receipts') diff --git a/packages/client/test/net/protocol/lesprotocol.spec.ts b/packages/client/test/net/protocol/lesprotocol.spec.ts index 2d5c413902..c3e195395c 100644 --- a/packages/client/test/net/protocol/lesprotocol.spec.ts +++ b/packages/client/test/net/protocol/lesprotocol.spec.ts @@ -1,3 +1,4 @@ +import { bytesToHex } from '@ethereumjs/util' import * as tape from 'tape' import { Chain } from '../../../lib/blockchain' @@ -66,23 +67,23 @@ tape('[LesProtocol]', (t) => { }) let status = p.encodeStatus() t.ok( - status.networkId.toString('hex') === '01' && - status.headTd.toString('hex') === '64' && + bytesToHex(status.networkId) === '01' && + bytesToHex(status.headTd) === '64' && status.headHash === '0xaa' && - status.headNum.toString('hex') === '64' && + bytesToHex(status.headNum) === '64' && status.genesisHash === '0xbb' && - status.forkID[0].toString('hex') === 'fc64ec04' && - status.forkID[1].toString('hex') === '118c30' && - status.recentTxLookup.toString('hex') === '01' && + bytesToHex(status.forkID[0]) === 'fc64ec04' && + bytesToHex(status.forkID[1]) === '118c30' && + bytesToHex(status.recentTxLookup) === '01' && status.serveHeaders === 1 && status.serveChainSince === 0 && status.serveStateSince === 0 && //status.txRelay === 1 && TODO: uncomment with client tx pool functionality - status['flowControl/BL'].toString('hex') === '03e8' && - status['flowControl/MRR'].toString('hex') === '0a' && - status['flowControl/MRC'][0][0].toString('hex') === '02' && - status['flowControl/MRC'][0][1].toString('hex') === '0a' && - status['flowControl/MRC'][0][2].toString('hex') === '0a', + bytesToHex(status['flowControl/BL']) === '03e8' && + bytesToHex(status['flowControl/MRR']) === '0a' && + bytesToHex(status['flowControl/MRC'][0][0]) === '02' && + bytesToHex(status['flowControl/MRC'][0][1]) === '0a' && + bytesToHex(status['flowControl/MRC'][0][2]) === '0a', 'encode status' ) status = { ...status, networkId: [0x01] } @@ -93,9 +94,9 @@ tape('[LesProtocol]', (t) => { status.headHash === '0xaa' && status.headNum === BigInt(100) && status.genesisHash === '0xbb' && - status.forkID[0].toString('hex') === 'fc64ec04' && - status.forkID[1].toString('hex') === '118c30' && - status.recentTxLookup.toString('hex') === '01' && + bytesToHex(status.forkID[0]) === 'fc64ec04' && + bytesToHex(status.forkID[1]) === '118c30' && + bytesToHex(status.recentTxLookup) === '01' && status.serveHeaders === true && status.serveChainSince === 0 && status.serveStateSince === 0 && diff --git a/packages/client/test/net/protocol/libp2psender.spec.ts b/packages/client/test/net/protocol/libp2psender.spec.ts index 156f0a3e1f..99cdbf8ce4 100644 --- a/packages/client/test/net/protocol/libp2psender.spec.ts +++ b/packages/client/test/net/protocol/libp2psender.spec.ts @@ -1,3 +1,4 @@ +import { bytesToHex, hexStringToBytes } from '@ethereumjs/util' import * as tape from 'tape' import { Libp2pSender } from '../../../lib/net/protocol' @@ -10,11 +11,11 @@ tape('[Libp2pSender]', (t) => { const sender = new Libp2pSender(conn[0]) const receiver = new Libp2pSender(conn[1]) receiver.on('status', (status: any) => { - t.equal(status.id.toString('hex'), '05', 'status received') - t.equal(receiver.status.id.toString('hex'), '05', 'status getter') + t.equal(bytesToHex(status.id), '05', 'status received') + t.equal(bytesToHex(receiver.status.id), '05', 'status getter') t.end() }) - sender.sendStatus({ id: Buffer.from('05', 'hex') }) + sender.sendStatus({ id: hexStringToBytes('05') }) }) t.test('should send/receive message', (t) => { @@ -23,10 +24,10 @@ tape('[Libp2pSender]', (t) => { const receiver = new Libp2pSender(conn[1]) receiver.on('message', (message: any) => { t.equal(message.code, 1, 'message received (code)') - t.equal(message.payload.toString('hex'), '05', 'message received (payload)') + t.equal(bytesToHex(message.payload), '05', 'message received (payload)') t.end() }) - sender.sendMessage(1, Buffer.from('05', 'hex')) + sender.sendMessage(1, hexStringToBytes('05')) }) t.test('should catch errors', (t) => { diff --git a/packages/client/test/net/protocol/snapprotocol.spec.ts b/packages/client/test/net/protocol/snapprotocol.spec.ts index aa9da76c40..a614a7fb6d 100644 --- a/packages/client/test/net/protocol/snapprotocol.spec.ts +++ b/packages/client/test/net/protocol/snapprotocol.spec.ts @@ -4,10 +4,14 @@ import { KECCAK256_NULL, KECCAK256_RLP, accountBodyToRLP, - bigIntToBuffer, + bigIntToBytes, + bytesToHex, + equalsBytes, + hexStringToBytes, setLengthLeft, } from '@ethereumjs/util' import { keccak256 } from 'ethereum-cryptography/keccak' +import { hexToBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' import { Chain } from '../../../lib/blockchain' @@ -43,15 +47,13 @@ tape('[SnapProtocol]', (t) => { const config = new Config({ transports: [] }) const chain = await Chain.create({ config }) const p = new SnapProtocol({ config, chain }) - const root = Buffer.from([]) + const root = new Uint8Array(0) const reqId = BigInt(1) - const origin = Buffer.from( - '0000000000000000000000000000000000000000000000000000000000000000', - 'hex' + const origin = hexStringToBytes( + '0000000000000000000000000000000000000000000000000000000000000000' ) - const limit = Buffer.from( - '0000000000000000000000000f00000000000000000000000000000000000010', - 'hex' + const limit = hexStringToBytes( + '0000000000000000000000000f00000000000000000000000000000000000010' ) const bytes = BigInt(5000000) @@ -67,7 +69,7 @@ tape('[SnapProtocol]', (t) => { ) t.ok( - JSON.stringify(payload[0]) === JSON.stringify(bigIntToBuffer(BigInt(1))), + JSON.stringify(payload[0]) === JSON.stringify(bigIntToBytes(BigInt(1))), 'correctly encoded reqId' ) t.ok( @@ -77,7 +79,7 @@ tape('[SnapProtocol]', (t) => { t.ok(JSON.stringify(payload[2]) === JSON.stringify(origin), 'correctly encoded origin') t.ok(JSON.stringify(payload[3]) === JSON.stringify(limit), 'correctly encoded limit') t.ok( - JSON.stringify(payload[4]) === JSON.stringify(bigIntToBuffer(bytes)), + JSON.stringify(payload[4]) === JSON.stringify(bigIntToBytes(bytes)), 'correctly encoded bytes' ) t.ok(payload) @@ -104,7 +106,7 @@ tape('[SnapProtocol]', (t) => { const chain = await Chain.create({ config }) const p = new SnapProtocol({ config, chain }) /* eslint-disable @typescript-eslint/no-use-before-define */ - const data = RLP.decode(Buffer.from(contractAccountRangeRLP, 'hex')) as unknown + const data = RLP.decode(hexStringToBytes(contractAccountRangeRLP)) as unknown const { reqId, accounts, proof } = p.decode( p.messages.filter((message) => message.name === 'AccountRange')[0], data @@ -119,12 +121,12 @@ tape('[SnapProtocol]', (t) => { t.ok(firstAccount[2].length === 0, 'Slim format storageRoot for first account') t.ok(firstAccount[3].length === 0, 'Slim format codehash for first account') t.ok( - secondAccount[2].toString('hex') === + bytesToHex(secondAccount[2]) === '3dc6d3cfdc6210b8591ea852961d880821298c7891dea399e02d87550af9d40e', 'storageHash of the second account' ) t.ok( - secondAccount[3].toString('hex') === + bytesToHex(secondAccount[3]) === 'e68fe0bb7c4a483affd0f19cc2b989105242bd6b256c6de3afd738f8acd80c66', 'codeHash of the second account' ) @@ -136,7 +138,7 @@ tape('[SnapProtocol]', (t) => { }) ) t.ok( - contractAccountRangeRLP === Buffer.from(payload).toString('hex'), + contractAccountRangeRLP === bytesToHex(payload), 'Re-encoded payload should match with original' ) t.end() @@ -148,7 +150,7 @@ tape('[SnapProtocol]', (t) => { const pSlim = new SnapProtocol({ config, chain }) const pFull = new SnapProtocol({ config, chain, convertSlimBody: true }) // accountRangeRLP is the corresponding response to getAccountRangeRLP - const resData = RLP.decode(Buffer.from(accountRangeRLP, 'hex')) as unknown + const resData = RLP.decode(hexStringToBytes(accountRangeRLP)) const fullData = pFull.decode( pFull.messages.filter((message) => message.name === 'AccountRange')[0], @@ -157,8 +159,8 @@ tape('[SnapProtocol]', (t) => { const { accounts: accountsFull } = fullData t.ok(accountsFull.length === 3, '3 accounts should be decoded in accountsFull') const accountFull = accountsFull[0].body - t.ok(accountFull[2].equals(KECCAK256_RLP), 'storageRoot should be KECCAK256_RLP') - t.ok(accountFull[3].equals(KECCAK256_NULL), 'codeHash should be KECCAK256_NULL') + t.ok(equalsBytes(accountFull[2], KECCAK256_RLP), 'storageRoot should be KECCAK256_RLP') + t.ok(equalsBytes(accountFull[3], KECCAK256_NULL), 'codeHash should be KECCAK256_NULL') // Lets encode fullData as it should be encoded in slim format and upon decoding // we shpuld get slim format @@ -186,13 +188,13 @@ tape('[SnapProtocol]', (t) => { const p = new SnapProtocol({ config, chain }) /* eslint-disable @typescript-eslint/no-use-before-define */ - const reqData = RLP.decode(Buffer.from(getAccountRangeRLP, 'hex')) + const reqData = RLP.decode(hexStringToBytes(getAccountRangeRLP)) const { root: stateRoot } = p.decode( p.messages.filter((message) => message.name === 'GetAccountRange')[0], reqData ) // accountRangeRLP is the corresponding response to getAccountRangeRLP - const resData = RLP.decode(Buffer.from(accountRangeRLP, 'hex')) as unknown + const resData = RLP.decode(hexStringToBytes(accountRangeRLP)) const { accounts, proof } = p.decode( p.messages.filter((message) => message.name === 'AccountRange')[0], resData @@ -214,7 +216,7 @@ tape('[SnapProtocol]', (t) => { t.fail(`AccountRange proof verification failed with message=${(e as Error).message}`) } t.ok( - Buffer.from(keccak256(proof[0])).toString('hex') === stateRoot.toString('hex'), + equalsBytes(keccak256(proof[0]), stateRoot), 'Proof should link to the requested stateRoot' ) t.end() @@ -224,20 +226,18 @@ tape('[SnapProtocol]', (t) => { const config = new Config({ transports: [] }) const chain = await Chain.create({ config }) const p = new SnapProtocol({ config, chain }) - const root = Buffer.from([]) + const root = new Uint8Array(0) const reqId = BigInt(1) - const origin = Buffer.from( - '0000000000000000000000000000000000000000000000000000000000000000', - 'hex' + const origin = hexStringToBytes( + '0000000000000000000000000000000000000000000000000000000000000000' ) - const limit = Buffer.from( - '0000000000000000000000000f00000000000000000000000000000000000010', - 'hex' + const limit = hexStringToBytes( + '0000000000000000000000000f00000000000000000000000000000000000010' ) const bytes = BigInt(5000000) const accounts = [ - Buffer.from(keccak256(Buffer.from('0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', 'hex'))), - Buffer.from('0000000000000000000000000f00000000000000000000000000000000000010', 'hex'), + keccak256(hexStringToBytes('0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')), + hexStringToBytes('0000000000000000000000000f00000000000000000000000000000000000010'), ] const payload = p.encode( @@ -253,7 +253,7 @@ tape('[SnapProtocol]', (t) => { ) t.ok( - JSON.stringify(payload[0]) === JSON.stringify(bigIntToBuffer(BigInt(1))), + JSON.stringify(payload[0]) === JSON.stringify(bigIntToBytes(BigInt(1))), 'correctly encoded reqId' ) t.ok( @@ -264,7 +264,7 @@ tape('[SnapProtocol]', (t) => { t.ok(JSON.stringify(payload[3]) === JSON.stringify(origin), 'correctly encoded origin') t.ok(JSON.stringify(payload[4]) === JSON.stringify(limit), 'correctly encoded limit') t.ok( - JSON.stringify(payload[5]) === JSON.stringify(bigIntToBuffer(bytes)), + JSON.stringify(payload[5]) === JSON.stringify(bigIntToBytes(bytes)), 'correctly encoded bytes' ) t.ok(payload) @@ -292,7 +292,7 @@ tape('[SnapProtocol]', (t) => { const p = new SnapProtocol({ config, chain }) /* eslint-disable @typescript-eslint/no-use-before-define */ - const data = RLP.decode(Buffer.from(storageRangesRLP, 'hex')) as unknown + const data = RLP.decode(hexStringToBytes(storageRangesRLP)) as unknown const { reqId, slots, proof } = p.decode( p.messages.filter((message) => message.name === 'StorageRanges')[0], data @@ -301,10 +301,10 @@ tape('[SnapProtocol]', (t) => { t.ok(slots.length === 1 && slots[0].length === 3, 'correctly decoded slots') const { hash, body } = slots[0][2] t.ok( - hash.toString('hex') === '60264186ee63f748d340388f07b244d96d007fff5cbc397bbd69f8747c421f79', + bytesToHex(hash) === '60264186ee63f748d340388f07b244d96d007fff5cbc397bbd69f8747c421f79', 'Slot 3 key' ) - t.ok(body.toString('hex') === '8462b66ae7', 'Slot 3 value') + t.ok(bytesToHex(body) === '8462b66ae7', 'Slot 3 value') const payload = RLP.encode( p.encode(p.messages.filter((message) => message.name === 'StorageRanges')[0], { @@ -313,10 +313,7 @@ tape('[SnapProtocol]', (t) => { proof, }) ) - t.ok( - storageRangesRLP === Buffer.from(payload).toString('hex'), - 'Re-encoded payload should match with original' - ) + t.ok(storageRangesRLP === bytesToHex(payload), 'Re-encoded payload should match with original') t.end() }) @@ -326,7 +323,7 @@ tape('[SnapProtocol]', (t) => { const p = new SnapProtocol({ config, chain }) // Get the handle on the data for the account for which storageRanges has been fetched - const accountsData = RLP.decode(Buffer.from(contractAccountRangeRLP, 'hex')) as unknown + const accountsData = RLP.decode(hexStringToBytes(contractAccountRangeRLP)) const { accounts } = p.decode( p.messages.filter((message) => message.name === 'AccountRange')[0], accountsData @@ -334,7 +331,7 @@ tape('[SnapProtocol]', (t) => { const lastAccount = accounts[accounts.length - 1] /* eslint-disable @typescript-eslint/no-use-before-define */ - const data = RLP.decode(Buffer.from(storageRangesRLP, 'hex')) as unknown + const data = RLP.decode(hexStringToBytes(storageRangesRLP)) const { proof, slots } = p.decode( p.messages.filter((message) => message.name === 'StorageRanges')[0], data @@ -359,7 +356,7 @@ tape('[SnapProtocol]', (t) => { t.fail(`StorageRange proof verification failed with message=${(e as Error).message}`) } t.ok( - Buffer.from(keccak256(proof[0])).toString('hex') === lastAccountStorageRoot.toString('hex'), + equalsBytes(keccak256(proof[0]), lastAccountStorageRoot), 'Proof should link to the accounts storageRoot' ) t.end() @@ -371,8 +368,8 @@ tape('[SnapProtocol]', (t) => { const p = new SnapProtocol({ config, chain }) const reqId = BigInt(1) const hashes = [ - Buffer.from(keccak256(Buffer.from('0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', 'hex'))), - Buffer.from('0000000000000000000000000f00000000000000000000000000000000000010', 'hex'), + keccak256(hexStringToBytes('0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')), + hexStringToBytes('0000000000000000000000000f00000000000000000000000000000000000010'), ] const bytes = BigInt(5000000) @@ -383,12 +380,12 @@ tape('[SnapProtocol]', (t) => { }) t.ok( - JSON.stringify(payload[0]) === JSON.stringify(bigIntToBuffer(BigInt(1))), + JSON.stringify(payload[0]) === JSON.stringify(bigIntToBytes(BigInt(1))), 'correctly encoded reqId' ) t.ok(JSON.stringify(payload[1]) === JSON.stringify(hashes), 'correctly encoded hashes') t.ok( - JSON.stringify(payload[2]) === JSON.stringify(bigIntToBuffer(bytes)), + JSON.stringify(payload[2]) === JSON.stringify(bigIntToBytes(bytes)), 'correctly encoded bytes' ) t.ok(payload) @@ -410,7 +407,7 @@ tape('[SnapProtocol]', (t) => { const chain = await Chain.create({ config }) const p = new SnapProtocol({ config, chain }) - const codesRes = RLP.decode(Buffer.from(byteCodesRLP, 'hex')) as unknown + const codesRes = RLP.decode(hexStringToBytes(byteCodesRLP)) const { reqId, codes } = p.decode( p.messages.filter((message) => message.name === 'ByteCodes')[0], codesRes @@ -425,10 +422,7 @@ tape('[SnapProtocol]', (t) => { codes, }) ) - t.ok( - byteCodesRLP === Buffer.from(payload).toString('hex'), - 'Re-encoded payload should match with original' - ) + t.ok(byteCodesRLP === bytesToHex(payload), 'Re-encoded payload should match with original') t.end() }) @@ -438,22 +432,19 @@ tape('[SnapProtocol]', (t) => { const p = new SnapProtocol({ config, chain }) /* eslint-disable @typescript-eslint/no-use-before-define */ - const codesReq = RLP.decode(Buffer.from(getByteCodesRLP, 'hex')) as unknown + const codesReq = RLP.decode(hexStringToBytes(getByteCodesRLP)) const { hashes } = p.decode( p.messages.filter((message) => message.name === 'GetByteCodes')[0], codesReq ) const codeHash = hashes[0] - const codesRes = RLP.decode(Buffer.from(byteCodesRLP, 'hex')) as unknown + const codesRes = RLP.decode(hexStringToBytes(byteCodesRLP)) const { codes } = p.decode( p.messages.filter((message) => message.name === 'ByteCodes')[0], codesRes ) const code = codes[0] - t.ok( - Buffer.from(keccak256(code)).toString('hex') === codeHash.toString('hex'), - 'Code should match the requested codeHash' - ) + t.ok(equalsBytes(keccak256(code), codeHash), 'Code should match the requested codeHash') t.end() }) @@ -463,11 +454,8 @@ tape('[SnapProtocol]', (t) => { const p = new SnapProtocol({ config, chain }) const reqId = BigInt(1) - const root = Buffer.from( - '04157502e6177a76ca4dbf7784e5ec1a926049db6a91e13efb70a095a72a45d9', - 'hex' - ) - const paths = [[Buffer.from('0x0', 'hex')], [Buffer.from('0x0', 'hex')]] + const root = hexToBytes('04157502e6177a76ca4dbf7784e5ec1a926049db6a91e13efb70a095a72a45d9') + const paths = [[hexToBytes('0x00')], [hexToBytes('0x00')]] const bytes = BigInt(5000000) const payload = p.encode(p.messages.filter((message) => message.name === 'GetTrieNodes')[0], { @@ -478,13 +466,13 @@ tape('[SnapProtocol]', (t) => { }) t.ok( - JSON.stringify(payload[0]) === JSON.stringify(bigIntToBuffer(reqId)), + JSON.stringify(payload[0]) === JSON.stringify(bigIntToBytes(reqId)), 'correctly encoded reqId' ) t.ok(JSON.stringify(payload[1]) === JSON.stringify(root), 'correctly encoded root') t.ok(JSON.stringify(payload[2]) === JSON.stringify(paths), 'correctly encoded paths') t.ok( - JSON.stringify(payload[3]) === JSON.stringify(bigIntToBuffer(bytes)), + JSON.stringify(payload[3]) === JSON.stringify(bigIntToBytes(bytes)), 'correctly encoded bytes' ) t.ok(payload) @@ -507,7 +495,7 @@ tape('[SnapProtocol]', (t) => { const chain = await Chain.create({ config }) const p = new SnapProtocol({ config, chain }) - const nodesRes = RLP.decode(Buffer.from(trieNodesRLP, 'hex')) as unknown + const nodesRes = RLP.decode(hexToBytes(trieNodesRLP)) as unknown const { reqId, nodes } = p.decode( p.messages.filter((message) => message.name === 'TrieNodes')[0], nodesRes @@ -518,7 +506,7 @@ tape('[SnapProtocol]', (t) => { // check that raw node data that exists is valid for (let i = 0; i < nodes.length; i++) { - const node: Buffer = nodes[i] + const node: Uint8Array = nodes[i] if (node !== null) { t.ok(decodeNode(node), 'raw node data should decode without error') } @@ -530,10 +518,7 @@ tape('[SnapProtocol]', (t) => { nodes, }) ) - t.ok( - trieNodesRLP === Buffer.from(payload).toString('hex'), - 'Re-encoded payload should match with original' - ) + t.ok(trieNodesRLP === bytesToHex(payload), 'Re-encoded payload should match with original') t.end() }) }) @@ -545,11 +530,10 @@ const accountRangeRLP = //await peer!.snap!.getAccountRange({ // root: stateRoot, -// origin: Buffer.from( -// '27be64f6a1510e4166b35201a920e543e0579df3b947b8743458736e51549f0c', -// 'hex' +// origin: hexToBytes( +// '27be64f6a1510e4166b35201a920e543e0579df3b947b8743458736e51549f0c' // ), -// limit: Buffer.from('f000000000000000000000000f00000000000000000000000000000000000010', 'hex'), +// limit: hexStringToBytes('f000000000000000000000000f00000000000000000000000000000000000010'), // bytes: BigInt(100), // }) const contractAccountRangeRLP = @@ -560,13 +544,11 @@ const contractAccountRangeRLP = // await peer!.snap!.getStorageRanges({ // root: stateRoot, // accounts: [ -// Buffer.from('27be7c29a7a7d6da542205ed52b91990e625039a545702874be74db9f40fb215', 'hex'), +// hexStringToBytes('27be7c29a7a7d6da542205ed52b91990e625039a545702874be74db9f40fb215'), // ], -// origin: Buffer.from( -// '0000000000000000000000000f00000000000000000000000000000000000000', -// 'hex' -// ), -// limit: Buffer.from('f000000000000000000000000f00000000000000000000000000000000000010', 'hex'), +// origin: hexStringToBytes( +// '0000000000000000000000000f00000000000000000000000000000000000000'), +// limit: hexStringToBytes('f000000000000000000000000f00000000000000000000000000000000000010'), // bytes: BigInt(100), // }) const _getStorageRangesRLP = @@ -576,7 +558,7 @@ const storageRangesRLP = // await peer!.snap!.getByteCodes({ // hashes: [ -// Buffer.from('e68fe0bb7c4a483affd0f19cc2b989105242bd6b256c6de3afd738f8acd80c66', 'hex'), +// hexStringToBytes('e68fe0bb7c4a483affd0f19cc2b989105242bd6b256c6de3afd738f8acd80c66'), // ], // bytes: BigInt(50000), // }) diff --git a/packages/client/test/net/server/libp2pserver.spec.ts b/packages/client/test/net/server/libp2pserver.spec.ts index 1685b8075c..ea5c249c43 100644 --- a/packages/client/test/net/server/libp2pserver.spec.ts +++ b/packages/client/test/net/server/libp2pserver.spec.ts @@ -1,3 +1,4 @@ +import { bytesToUtf8, utf8ToBytes } from 'ethereum-cryptography/utils' import { EventEmitter } from 'events' import { multiaddr } from 'multiaddr' import * as tape from 'tape' @@ -50,7 +51,7 @@ tape('[Libp2pServer]', async (t) => { config, multiaddrs, bootnodes: ['0.0.0.0:3030', '1.1.1.1:3031'], - key: Buffer.from('abcd'), + key: utf8ToBytes('abcd'), }) t.deepEquals((server as any).multiaddrs, multiaddrs, 'multiaddrs correct') t.deepEquals( @@ -58,7 +59,7 @@ tape('[Libp2pServer]', async (t) => { [multiaddr('/ip4/0.0.0.0/tcp/3030'), multiaddr('/ip4/1.1.1.1/tcp/3031')], 'bootnodes split' ) - t.equals(server.key!.toString(), 'abcd', 'key is correct') + t.equals(bytesToUtf8(server.key!), 'abcd', 'key is correct') t.equals(server.name, 'libp2p', 'get name') t.equals( (await server.getPeerId()).toB58String(), @@ -96,7 +97,7 @@ tape('[Libp2pServer]', async (t) => { t.plan(12) const config = new Config({ transports: [], logger: getLogger({ loglevel: 'off' }) }) const multiaddrs = [multiaddr('/ip4/6.6.6.6')] - const server = new Libp2pServer({ config, multiaddrs, key: Buffer.from('4') }) + const server = new Libp2pServer({ config, multiaddrs, key: utf8ToBytes('4') }) const protos: any = [ { name: 'proto', versions: [1] }, { name: 'proto', versions: [2] }, diff --git a/packages/client/test/net/server/rlpxserver.spec.ts b/packages/client/test/net/server/rlpxserver.spec.ts index 6bfd7fbd5e..f34ef52380 100644 --- a/packages/client/test/net/server/rlpxserver.spec.ts +++ b/packages/client/test/net/server/rlpxserver.spec.ts @@ -1,3 +1,4 @@ +import { equalsBytes, hexStringToBytes, utf8ToBytes } from '@ethereumjs/util' import { EventEmitter } from 'events' import { multiaddr } from 'multiaddr' import * as tape from 'tape' @@ -10,7 +11,7 @@ tape('[RlpxServer]', async (t) => { class RlpxPeer extends EventEmitter { accept(_: any, _2: any) {} getId() { - return Buffer.from([1]) + return new Uint8Array([1]) } getDisconnectPrefix(_: any) { return 'MockedReason' @@ -51,7 +52,7 @@ tape('[RlpxServer]', async (t) => { key: 'abcd', }) t.equals(server.name, 'rlpx', 'get name') - t.ok(server.key!.equals(Buffer.from('abcd', 'hex')), 'key parse') + t.ok(equalsBytes(server.key!, hexStringToBytes('abcd')), 'key parse') t.deepEquals( server.bootnodes, [multiaddr('/ip4/10.0.0.1/tcp/1234'), multiaddr('/ip4/10.0.0.2/tcp/1234')], @@ -111,7 +112,7 @@ tape('[RlpxServer]', async (t) => { t.test('should return rlpx server info with ip4 as default', async (t) => { const config = new Config({ transports: [] }) - const mockId = '123' + const mockId = '0123' const server = new RlpxServer({ config, bootnodes: '10.0.0.1:1234,10.0.0.2:1234', @@ -120,9 +121,9 @@ tape('[RlpxServer]', async (t) => { ;(server as any).initRlpx = td.func() server.dpt = td.object() ;(server as any).rlpx = td.object({ - _id: mockId, destroy: td.func(), }) + server.rlpx!._id = hexStringToBytes(mockId) td.when( server.dpt!.bootstrap({ address: '10.0.0.1', udpPort: 1234, tcpPort: 1234 }) ).thenResolve(undefined) @@ -130,6 +131,7 @@ tape('[RlpxServer]', async (t) => { (server.dpt! as any).bootstrap({ address: '10.0.0.2', udpPort: '1234', tcpPort: '1234' }) ).thenReject(new Error('err0')) config.events.on(Event.SERVER_ERROR, (err) => t.equals(err.message, 'err0', 'got error')) + await server.start() const nodeInfo = server.getRlpxInfo() t.deepEqual( @@ -149,7 +151,7 @@ tape('[RlpxServer]', async (t) => { t.test('should return rlpx server info with ip6', async (t) => { const config = new Config({ transports: [], extIP: '::' }) - const mockId = '123' + const mockId = '0123' const server = new RlpxServer({ config, bootnodes: '10.0.0.1:1234,10.0.0.2:1234', @@ -158,9 +160,9 @@ tape('[RlpxServer]', async (t) => { ;(server as any).initRlpx = td.func() server.dpt = td.object() ;(server as any).rlpx = td.object({ - _id: mockId, destroy: td.func(), }) + server.rlpx!._id = hexStringToBytes(mockId) td.when( server.dpt!.bootstrap({ address: '10.0.0.1', udpPort: 1234, tcpPort: 1234 }) ).thenResolve(undefined) @@ -231,7 +233,7 @@ tape('[RlpxServer]', async (t) => { const config = new Config({ transports: [] }) const server = new RlpxServer({ config }) const rlpxPeer = new RlpxPeer() - td.when(rlpxPeer.getId()).thenReturn(Buffer.from([1])) + td.when(rlpxPeer.getId()).thenReturn(new Uint8Array([1])) td.when(RlpxPeer.prototype.accept(rlpxPeer, td.matchers.isA(RlpxServer))).thenResolve() ;(server as any).initRlpx().catch((error: Error) => { throw error @@ -248,7 +250,7 @@ tape('[RlpxServer]', async (t) => { ;(server as any).peers.set('01', { id: '01' } as any) server.rlpx!.emit('peer:removed', rlpxPeer) server.rlpx!.emit('peer:error', rlpxPeer, new Error('err0')) - server.rlpx!._id = Buffer.from('ff', 'hex') + server.rlpx!._id = hexStringToBytes('ff') server.rlpx!.emit('listening') }) @@ -257,7 +259,7 @@ tape('[RlpxServer]', async (t) => { const config = new Config({ transports: [] }) const server = new RlpxServer({ config }) const rlpxPeer = new RlpxPeer() - td.when(rlpxPeer.getId()).thenReturn(Buffer.from('test')) + td.when(rlpxPeer.getId()).thenReturn(utf8ToBytes('test')) td.when(RlpxPeer.prototype.accept(rlpxPeer, td.matchers.isA(RlpxServer))).thenResolve() ;(server as any).initRlpx().catch((error: Error) => { throw error diff --git a/packages/client/test/rpc/debug/traceTransaction.spec.ts b/packages/client/test/rpc/debug/traceTransaction.spec.ts index 88eca2a3d1..48ef13e181 100644 --- a/packages/client/test/rpc/debug/traceTransaction.spec.ts +++ b/packages/client/test/rpc/debug/traceTransaction.spec.ts @@ -1,6 +1,6 @@ import { Block } from '@ethereumjs/block' import { TransactionFactory } from '@ethereumjs/tx' -import { bufferToHex } from '@ethereumjs/util' +import { bytesToPrefixedHexString } from '@ethereumjs/util' import * as tape from 'tape' import { INTERNAL_ERROR, INVALID_PARAMS } from '../../../lib/rpc/error-code' @@ -70,7 +70,7 @@ tape(`${method}: call with valid parameters`, async (t) => { block.transactions[0] = tx await runBlockWithTxs(chain, execution, [tx], true) - const req = params(method, [bufferToHex(tx.hash()), {}]) + const req = params(method, [bytesToPrefixedHexString(tx.hash()), {}]) const expectRes = (res: any) => { t.equal(res.body.result.structLogs[0].op, 'PUSH1', 'produced a correct trace') } @@ -101,7 +101,7 @@ tape(`${method}: call with reverting code`, async (t) => { block.transactions[0] = tx await runBlockWithTxs(chain, execution, [tx], true) - const req = params(method, [bufferToHex(tx.hash()), {}]) + const req = params(method, [bytesToPrefixedHexString(tx.hash()), {}]) const expectRes = (res: any) => { t.equal(res.body.result.failed, true, 'returns error result with reverting code') } @@ -132,7 +132,7 @@ tape(`${method}: call with memory enabled`, async (t) => { block.transactions[0] = tx await runBlockWithTxs(chain, execution, [tx], true) - const req = params(method, [bufferToHex(tx.hash()), { enableMemory: true }]) + const req = params(method, [bytesToPrefixedHexString(tx.hash()), { enableMemory: true }]) const expectRes = (res: any) => { t.equal( res.body.result.structLogs[5].memory[0], @@ -167,7 +167,7 @@ tape(`${method}: call with stack disabled`, async (t) => { block.transactions[0] = tx await runBlockWithTxs(chain, execution, [tx], true) - const req = params(method, [bufferToHex(tx.hash()), { disableStack: true }]) + const req = params(method, [bytesToPrefixedHexString(tx.hash()), { disableStack: true }]) const expectRes = (res: any) => { t.ok(res.body.result.structLogs[1].stack === undefined, 'returns no stack with trace') } diff --git a/packages/client/test/rpc/engine/forkchoiceUpdatedV1.spec.ts b/packages/client/test/rpc/engine/forkchoiceUpdatedV1.spec.ts index 69471e4cc0..feacb433fb 100644 --- a/packages/client/test/rpc/engine/forkchoiceUpdatedV1.spec.ts +++ b/packages/client/test/rpc/engine/forkchoiceUpdatedV1.spec.ts @@ -1,6 +1,6 @@ import { Block, BlockHeader } from '@ethereumjs/block' import { Chain, Common, Hardfork } from '@ethereumjs/common' -import { bufferToHex, zeros } from '@ethereumjs/util' +import { bytesToHex, bytesToPrefixedHexString, zeros } from '@ethereumjs/util' import * as tape from 'tape' import * as td from 'testdouble' @@ -161,7 +161,7 @@ tape(`${method}: invalid terminal block with only genesis block`, async (t) => { const req = params(method, [validForkChoiceState, null]) const expectRes = (res: any) => { t.equal(res.body.result.payloadStatus.status, 'INVALID') - t.equal(res.body.result.payloadStatus.latestValidHash, bufferToHex(zeros(32))) + t.equal(res.body.result.payloadStatus.latestValidHash, bytesToHex(zeros(32))) } await baseRequest(t, server, req, 200, expectRes) }) @@ -187,7 +187,7 @@ tape(`${method}: invalid terminal block with 1+ blocks`, async (t) => { number: blocks[0].blockNumber, parentHash: blocks[0].parentHash, difficulty: 1, - extraData: Buffer.alloc(97), + extraData: new Uint8Array(97), }, }, { common } @@ -195,12 +195,12 @@ tape(`${method}: invalid terminal block with 1+ blocks`, async (t) => { await chain.putBlocks([newBlock]) const req = params(method, [ - { ...validForkChoiceState, headBlockHash: '0x' + newBlock.hash().toString('hex') }, + { ...validForkChoiceState, headBlockHash: bytesToPrefixedHexString(newBlock.hash()) }, null, ]) const expectRes = (res: any) => { t.equal(res.body.result.payloadStatus.status, 'INVALID') - t.equal(res.body.result.payloadStatus.latestValidHash, bufferToHex(zeros(32))) + t.equal(res.body.result.payloadStatus.latestValidHash, bytesToHex(zeros(32))) } await baseRequest(t, server, req, 200, expectRes) }) diff --git a/packages/client/test/rpc/engine/getBlobsBundleV1.spec.ts b/packages/client/test/rpc/engine/getBlobsBundleV1.spec.ts index d3aaab349f..ce608ca7a8 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 } from '@ethereumjs/util' +import { Address, hexStringToBytes } from '@ethereumjs/util' import * as kzg from 'c-kzg' import * as tape from 'tape' @@ -61,10 +61,7 @@ tape(`${method}: call with known payload`, async (t) => { hardfork: Hardfork.ShardingForkDev, }) common.setHardfork(Hardfork.ShardingForkDev) - const pkey = Buffer.from( - '9c9996335451aab4fc4eac58e31a8c300e095cdbcee532d53d09280e83360355', - 'hex' - ) + const pkey = hexStringToBytes('9c9996335451aab4fc4eac58e31a8c300e095cdbcee532d53d09280e83360355') const address = Address.fromPrivateKey(pkey) const account = await service.execution.vm.stateManager.getAccount(address) diff --git a/packages/client/test/rpc/engine/getPayloadBodiesByHashV1.spec.ts b/packages/client/test/rpc/engine/getPayloadBodiesByHashV1.spec.ts index f776bed5f9..32fb207324 100644 --- a/packages/client/test/rpc/engine/getPayloadBodiesByHashV1.spec.ts +++ b/packages/client/test/rpc/engine/getPayloadBodiesByHashV1.spec.ts @@ -2,8 +2,7 @@ import { Block, BlockHeader } from '@ethereumjs/block' import { Hardfork } from '@ethereumjs/common' import { DefaultStateManager } from '@ethereumjs/statemanager' import { TransactionFactory } from '@ethereumjs/tx' -import { Address } from '@ethereumjs/util' -import { randomBytes } from 'crypto' +import { Address, bytesToPrefixedHexString, hexStringToBytes, randomBytes } from '@ethereumjs/util' import * as tape from 'tape' import { TOO_LARGE_REQUEST } from '../../../lib/rpc/error-code' @@ -18,7 +17,7 @@ tape(`${method}: call with too many hashes`, async (t) => { const { server } = baseSetup({ engine: true, includeVM: true }) const tooManyHashes: string[] = [] for (let x = 0; x < 35; x++) { - tooManyHashes.push('0x' + randomBytes(32).toString('hex')) + tooManyHashes.push(bytesToPrefixedHexString(randomBytes(32))) } const req = params(method, [tooManyHashes]) const expectRes = checkError( @@ -42,10 +41,7 @@ tape(`${method}: call with valid parameters`, async (t) => { hardfork: Hardfork.ShardingForkDev, }) common.setHardfork(Hardfork.ShardingForkDev) - const pkey = Buffer.from( - '9c9996335451aab4fc4eac58e31a8c300e095cdbcee532d53d09280e83360355', - 'hex' - ) + const pkey = hexStringToBytes('9c9996335451aab4fc4eac58e31a8c300e095cdbcee532d53d09280e83360355') const address = Address.fromPrivateKey(pkey) const account = await service.execution.vm.stateManager.getAccount(address) @@ -97,15 +93,15 @@ tape(`${method}: call with valid parameters`, async (t) => { const req = params(method, [ [ - '0x' + block.hash().toString('hex'), - '0x' + randomBytes(32).toString('hex'), - '0x' + block2.hash().toString('hex'), + bytesToPrefixedHexString(block.hash()), + bytesToPrefixedHexString(randomBytes(32)), + bytesToPrefixedHexString(block2.hash()), ], ]) const expectRes = (res: any) => { t.equal( res.body.result[0].transactions[0], - '0x' + tx.serialize().toString('hex'), + bytesToPrefixedHexString(tx.serialize()), 'got expected transaction from first payload' ) t.equal(res.body.result[1], null, 'got null for block not found in chain') @@ -134,10 +130,7 @@ tape(`${method}: call with valid parameters on pre-Shanghai block`, async (t) => } ) common.setHardfork(Hardfork.London) - const pkey = Buffer.from( - '9c9996335451aab4fc4eac58e31a8c300e095cdbcee532d53d09280e83360355', - 'hex' - ) + const pkey = hexStringToBytes('9c9996335451aab4fc4eac58e31a8c300e095cdbcee532d53d09280e83360355') const address = Address.fromPrivateKey(pkey) const account = await service.execution.vm.stateManager.getAccount(address) @@ -189,9 +182,9 @@ tape(`${method}: call with valid parameters on pre-Shanghai block`, async (t) => const req = params(method, [ [ - '0x' + block.hash().toString('hex'), - '0x' + randomBytes(32).toString('hex'), - '0x' + block2.hash().toString('hex'), + bytesToPrefixedHexString(block.hash()), + bytesToPrefixedHexString(randomBytes(32)), + bytesToPrefixedHexString(block2.hash()), ], ]) const expectRes = (res: any) => { diff --git a/packages/client/test/rpc/engine/getPayloadBodiesByRangeV1.spec.ts b/packages/client/test/rpc/engine/getPayloadBodiesByRangeV1.spec.ts index ed63d819c1..e83ba7d41e 100644 --- a/packages/client/test/rpc/engine/getPayloadBodiesByRangeV1.spec.ts +++ b/packages/client/test/rpc/engine/getPayloadBodiesByRangeV1.spec.ts @@ -2,7 +2,7 @@ import { Block, BlockHeader } from '@ethereumjs/block' import { Hardfork } from '@ethereumjs/common' import { DefaultStateManager } from '@ethereumjs/statemanager' import { TransactionFactory } from '@ethereumjs/tx' -import { Address } from '@ethereumjs/util' +import { Address, bytesToPrefixedHexString, hexStringToBytes } from '@ethereumjs/util' import * as tape from 'tape' import { INVALID_PARAMS, TOO_LARGE_REQUEST } from '../../../lib/rpc/error-code' @@ -50,10 +50,7 @@ tape(`${method}: call with valid parameters`, async (t) => { hardfork: Hardfork.ShardingForkDev, }) common.setHardfork(Hardfork.ShardingForkDev) - const pkey = Buffer.from( - '9c9996335451aab4fc4eac58e31a8c300e095cdbcee532d53d09280e83360355', - 'hex' - ) + const pkey = hexStringToBytes('9c9996335451aab4fc4eac58e31a8c300e095cdbcee532d53d09280e83360355') const address = Address.fromPrivateKey(pkey) const account = await service.execution.vm.stateManager.getAccount(address) @@ -107,7 +104,7 @@ tape(`${method}: call with valid parameters`, async (t) => { const expectRes = (res: any) => { t.equal( res.body.result[0].transactions[0], - '0x' + tx.serialize().toString('hex'), + bytesToPrefixedHexString(tx.serialize()), 'got expected transaction from first payload' ) t.equal( @@ -145,10 +142,7 @@ tape(`${method}: call with valid parameters on pre-Shanghai hardfork`, async (t) hardfork: Hardfork.London, }) common.setHardfork(Hardfork.London) - const pkey = Buffer.from( - '9c9996335451aab4fc4eac58e31a8c300e095cdbcee532d53d09280e83360355', - 'hex' - ) + const pkey = hexStringToBytes('9c9996335451aab4fc4eac58e31a8c300e095cdbcee532d53d09280e83360355') const address = Address.fromPrivateKey(pkey) const account = await service.execution.vm.stateManager.getAccount(address) diff --git a/packages/client/test/rpc/engine/newPayloadV1.spec.ts b/packages/client/test/rpc/engine/newPayloadV1.spec.ts index 73477dd1d0..0f98f83415 100644 --- a/packages/client/test/rpc/engine/newPayloadV1.spec.ts +++ b/packages/client/test/rpc/engine/newPayloadV1.spec.ts @@ -1,6 +1,6 @@ import { BlockHeader } from '@ethereumjs/block' import { FeeMarketEIP1559Transaction } from '@ethereumjs/tx' -import { Address, bufferToHex, zeros } from '@ethereumjs/util' +import { Address, bytesToPrefixedHexString, hexStringToBytes, zeros } from '@ethereumjs/util' import * as tape from 'tape' import * as td from 'testdouble' @@ -152,7 +152,7 @@ tape(`${method}: invalid terminal block`, async (t) => { const req = params(method, [blockData, null]) const expectRes = (res: any) => { t.equal(res.body.result.status, 'INVALID') - t.equal(res.body.result.latestValidHash, bufferToHex(zeros(32))) + t.equal(res.body.result.latestValidHash, bytesToPrefixedHexString(zeros(32))) } await baseRequest(t, server, req, 200, expectRes) }) @@ -203,7 +203,7 @@ tape(`${method}: call with valid data & valid transaction but not signed`, async { common } ) - const transactions = ['0x' + tx.serialize().toString('hex')] + const transactions = [bytesToPrefixedHexString(tx.serialize())] const blockDataWithValidTransaction = { ...blockData, transactions, @@ -219,9 +219,8 @@ tape(`${method}: call with valid data & valid transaction but not signed`, async }) tape(`${method}: call with valid data & valid transaction`, async (t) => { - const accountPk = Buffer.from( - 'e331b6d69882b4cb4ea581d88e0b604039a3de5967688d3dcffdd2270c0fd109', - 'hex' + const accountPk = hexStringToBytes( + 'e331b6d69882b4cb4ea581d88e0b604039a3de5967688d3dcffdd2270c0fd109' ) const accountAddress = Address.fromPrivateKey(accountPk) const newGenesisJSON = { @@ -244,7 +243,7 @@ tape(`${method}: call with valid data & valid transaction`, async (t) => { }, { common } ).sign(accountPk) - const transactions = ['0x' + tx.serialize().toString('hex')] + const transactions = [bytesToPrefixedHexString(tx.serialize())] const blockDataWithValidTransaction = { ...blockData, transactions, diff --git a/packages/client/test/rpc/engine/newPayloadv2.spec.ts b/packages/client/test/rpc/engine/newPayloadv2.spec.ts index 03458e31d2..425d485af6 100644 --- a/packages/client/test/rpc/engine/newPayloadv2.spec.ts +++ b/packages/client/test/rpc/engine/newPayloadv2.spec.ts @@ -1,6 +1,6 @@ import { BlockHeader } from '@ethereumjs/block' import { FeeMarketEIP1559Transaction } from '@ethereumjs/tx' -import { Address, bufferToHex, zeros } from '@ethereumjs/util' +import { Address, bytesToPrefixedHexString, hexStringToBytes, zeros } from '@ethereumjs/util' import * as tape from 'tape' import * as td from 'testdouble' @@ -147,7 +147,7 @@ tape(`${method}: call with executionPayloadV1`, (v1) => { const req = params(method, [blockData, null]) const expectRes = (res: any) => { t.equal(res.body.result.status, 'INVALID') - t.equal(res.body.result.latestValidHash, bufferToHex(zeros(32))) + t.equal(res.body.result.latestValidHash, bytesToPrefixedHexString(zeros(32))) } await baseRequest(t, server, req, 200, expectRes) }) @@ -198,7 +198,7 @@ tape(`${method}: call with executionPayloadV1`, (v1) => { { common } ) - const transactions = ['0x' + tx.serialize().toString('hex')] + const transactions = [bytesToPrefixedHexString(tx.serialize())] const blockDataWithValidTransaction = { ...blockData, transactions, @@ -214,9 +214,8 @@ tape(`${method}: call with executionPayloadV1`, (v1) => { }) v1.test(`${method}: call with valid data & valid transaction`, async (t) => { - const accountPk = Buffer.from( - 'e331b6d69882b4cb4ea581d88e0b604039a3de5967688d3dcffdd2270c0fd109', - 'hex' + const accountPk = hexStringToBytes( + 'e331b6d69882b4cb4ea581d88e0b604039a3de5967688d3dcffdd2270c0fd109' ) const accountAddress = Address.fromPrivateKey(accountPk) const newGenesisJSON = { @@ -239,7 +238,7 @@ tape(`${method}: call with executionPayloadV1`, (v1) => { }, { common } ).sign(accountPk) - const transactions = ['0x' + tx.serialize().toString('hex')] + const transactions = [bytesToPrefixedHexString(tx.serialize())] const blockDataWithValidTransaction = { ...blockData, transactions, diff --git a/packages/client/test/rpc/engine/newPayloadv3.spec.ts b/packages/client/test/rpc/engine/newPayloadv3.spec.ts index 39b1879056..efa1e8696b 100644 --- a/packages/client/test/rpc/engine/newPayloadv3.spec.ts +++ b/packages/client/test/rpc/engine/newPayloadv3.spec.ts @@ -1,6 +1,6 @@ import { BlockHeader } from '@ethereumjs/block' import { FeeMarketEIP1559Transaction } from '@ethereumjs/tx' -import { Address, bufferToHex, zeros } from '@ethereumjs/util' +import { Address, bytesToPrefixedHexString, hexStringToBytes, zeros } from '@ethereumjs/util' import * as tape from 'tape' import * as td from 'testdouble' @@ -147,7 +147,7 @@ tape(`${method}: call with executionPayloadV1`, (v1) => { const req = params(method, [blockData, null]) const expectRes = (res: any) => { t.equal(res.body.result.status, 'INVALID') - t.equal(res.body.result.latestValidHash, bufferToHex(zeros(32))) + t.equal(res.body.result.latestValidHash, bytesToPrefixedHexString(zeros(32))) } await baseRequest(t, server, req, 200, expectRes) }) @@ -198,7 +198,7 @@ tape(`${method}: call with executionPayloadV1`, (v1) => { { common } ) - const transactions = ['0x' + tx.serialize().toString('hex')] + const transactions = [bytesToPrefixedHexString(tx.serialize())] const blockDataWithValidTransaction = { ...blockData, transactions, @@ -214,9 +214,8 @@ tape(`${method}: call with executionPayloadV1`, (v1) => { }) v1.test(`${method}: call with valid data & valid transaction`, async (t) => { - const accountPk = Buffer.from( - 'e331b6d69882b4cb4ea581d88e0b604039a3de5967688d3dcffdd2270c0fd109', - 'hex' + const accountPk = hexStringToBytes( + 'e331b6d69882b4cb4ea581d88e0b604039a3de5967688d3dcffdd2270c0fd109' ) const accountAddress = Address.fromPrivateKey(accountPk) const newGenesisJSON = { @@ -239,7 +238,7 @@ tape(`${method}: call with executionPayloadV1`, (v1) => { }, { common } ).sign(accountPk) - const transactions = ['0x' + tx.serialize().toString('hex')] + const transactions = [bytesToPrefixedHexString(tx.serialize())] const blockDataWithValidTransaction = { ...blockData, transactions, diff --git a/packages/client/test/rpc/engine/withdrawals.spec.ts b/packages/client/test/rpc/engine/withdrawals.spec.ts index 830ffa90e0..11fc32311d 100644 --- a/packages/client/test/rpc/engine/withdrawals.spec.ts +++ b/packages/client/test/rpc/engine/withdrawals.spec.ts @@ -1,5 +1,5 @@ import { Block } from '@ethereumjs/block' -import { Withdrawal, bigIntToHex, intToHex } from '@ethereumjs/util' +import { Withdrawal, bigIntToHex, bytesToHex, intToHex } from '@ethereumjs/util' import * as tape from 'tape' import { INVALID_PARAMS } from '../../../lib/rpc/error-code' @@ -103,9 +103,9 @@ for (const { name, withdrawals, withdrawalsRoot, gethBlockRlp } of testCases) { const validPayloadAttributesWithWithdrawals = { ...validPayloadAttributes, withdrawals } tape(name, async (t) => { // check withdrawals root computation - const computedWithdrawalsRoot = ( + const computedWithdrawalsRoot = bytesToHex( await Block.genWithdrawalsTrieRoot(withdrawals.map(Withdrawal.fromWithdrawalData)) - ).toString('hex') + ) t.equal(withdrawalsRoot, computedWithdrawalsRoot, 'withdrawalsRoot compuation should match') const { server } = await setupChain(genesisJSON, 'post-merge', { engine: true }) diff --git a/packages/client/test/rpc/eth/call.spec.ts b/packages/client/test/rpc/eth/call.spec.ts index 9c13c9b429..205f66607e 100644 --- a/packages/client/test/rpc/eth/call.spec.ts +++ b/packages/client/test/rpc/eth/call.spec.ts @@ -2,7 +2,7 @@ import { Block } from '@ethereumjs/block' import { Blockchain } from '@ethereumjs/blockchain' import { Chain, Common, Hardfork } from '@ethereumjs/common' import { Transaction } from '@ethereumjs/tx' -import { Address, bigIntToHex, bufferToHex } from '@ethereumjs/util' +import { Address, bigIntToHex, bytesToPrefixedHexString } from '@ethereumjs/util' import * as tape from 'tape' import { INVALID_PARAMS } from '../../../lib/rpc/error-code' @@ -36,7 +36,7 @@ tape(`${method}: call with valid arguments`, async (t) => { /* // SPDX-License-Identifier: MIT pragma solidity ^0.7.4; - + contract HelloWorld { function myAddress() public view returns (address addr) { return msg.sender; @@ -98,21 +98,25 @@ tape(`${method}: call with valid arguments`, async (t) => { let req = params(method, [{ ...estimateTxData, gas: estimateTxData.gasLimit }, 'latest']) let expectRes = (res: any) => { const msg = 'should return the correct return value' - t.equal(res.body.result, bufferToHex(execResult.returnValue), msg) + t.equal(res.body.result, bytesToPrefixedHexString(execResult.returnValue), msg) } await baseRequest(t, server, req, 200, expectRes, false) req = params(method, [{ ...estimateTxData }, 'latest']) expectRes = (res: any) => { const msg = 'should return the correct return value with no gas limit provided' - t.equal(res.body.result, bufferToHex(execResult.returnValue), msg) + t.equal(res.body.result, bytesToPrefixedHexString(execResult.returnValue), msg) } await baseRequest(t, server, req, 200, expectRes, false) req = params(method, [{ gasLimit, data }, 'latest']) expectRes = (res: any) => { const msg = `should let run call without 'to' for contract creation` - t.equal(res.body.result, bufferToHex(result.results[0].execResult.returnValue), msg) + t.equal( + res.body.result, + bytesToPrefixedHexString(result.results[0].execResult.returnValue), + msg + ) } await baseRequest(t, server, req, 200, expectRes, true) }) diff --git a/packages/client/test/rpc/eth/getBlockByNumber.spec.ts b/packages/client/test/rpc/eth/getBlockByNumber.spec.ts index 9751fa3ac5..7bf3ed7c30 100644 --- a/packages/client/test/rpc/eth/getBlockByNumber.spec.ts +++ b/packages/client/test/rpc/eth/getBlockByNumber.spec.ts @@ -1,5 +1,6 @@ import { Block } from '@ethereumjs/block' import { Transaction } from '@ethereumjs/tx' +import { hexStringToBytes } from '@ethereumjs/util' import * as tape from 'tape' import { INVALID_PARAMS } from '../../../lib/rpc/error-code' @@ -10,13 +11,11 @@ const mockedTx1 = Transaction.fromTxData({}).sign(dummy.privKey) const mockedTx2 = Transaction.fromTxData({ nonce: 1 }).sign(dummy.privKey) function createChain() { - const genesisBlockHash = Buffer.from( - 'dcf93da321b27bca12087d6526d2c10540a4c8dc29db1b36610c3004e0e5d2d5', - 'hex' + const genesisBlockHash = hexStringToBytes( + 'dcf93da321b27bca12087d6526d2c10540a4c8dc29db1b36610c3004e0e5d2d5' ) - const blockHash = Buffer.from( - 'dcf93da321b27bca12087d6526d2c10540a4c8dc29db1b36610c3004e0e5d2d5', - 'hex' + const blockHash = hexStringToBytes( + 'dcf93da321b27bca12087d6526d2c10540a4c8dc29db1b36610c3004e0e5d2d5' ) const transactions = [mockedTx1] const transactions2 = [mockedTx2] diff --git a/packages/client/test/rpc/eth/getLogs.spec.ts b/packages/client/test/rpc/eth/getLogs.spec.ts index 1a3811e26c..27f67441b6 100644 --- a/packages/client/test/rpc/eth/getLogs.spec.ts +++ b/packages/client/test/rpc/eth/getLogs.spec.ts @@ -1,5 +1,5 @@ import { Transaction } from '@ethereumjs/tx' -import { Address, bufferToHex } from '@ethereumjs/util' +import { Address, bytesToPrefixedHexString, hexStringToBytes } from '@ethereumjs/util' import * as tape from 'tape' import { INVALID_PARAMS } from '../../../lib/rpc/error-code' @@ -24,9 +24,8 @@ const method = 'eth_getLogs' } ``` */ -const logExampleBytecode = Buffer.from( - '608060405234801561001057600080fd5b50610257806100206000396000f3fe608060405234801561001057600080fd5b5060043610610048576000357c010000000000000000000000000000000000000000000000000000000090048063aefb4f0a1461004d575b600080fd5b610067600480360381019061006291906100de565b610069565b005b60005b858110156100c1578284867fbf642f3055e2ef2589825c2c0dd4855c1137a63f6260d9d112629e5cd034a3eb856040516100a69190610168565b60405180910390a480806100b99061018d565b91505061006c565b505050505050565b6000813590506100d88161020a565b92915050565b600080600080600060a086880312156100fa576100f9610205565b5b6000610108888289016100c9565b9550506020610119888289016100c9565b945050604061012a888289016100c9565b935050606061013b888289016100c9565b925050608061014c888289016100c9565b9150509295509295909350565b61016281610183565b82525050565b600060208201905061017d6000830184610159565b92915050565b6000819050919050565b600061019882610183565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8214156101cb576101ca6101d6565b5b600182019050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600080fd5b61021381610183565b811461021e57600080fd5b5056fea2646970667358221220b98f45f4d4112e71fd287ab0ce7cc1872e53b463eb0abf1182b892192d3d8a1d64736f6c63430008070033', - 'hex' +const logExampleBytecode = hexStringToBytes( + '608060405234801561001057600080fd5b50610257806100206000396000f3fe608060405234801561001057600080fd5b5060043610610048576000357c010000000000000000000000000000000000000000000000000000000090048063aefb4f0a1461004d575b600080fd5b610067600480360381019061006291906100de565b610069565b005b60005b858110156100c1578284867fbf642f3055e2ef2589825c2c0dd4855c1137a63f6260d9d112629e5cd034a3eb856040516100a69190610168565b60405180910390a480806100b99061018d565b91505061006c565b505050505050565b6000813590506100d88161020a565b92915050565b600080600080600060a086880312156100fa576100f9610205565b5b6000610108888289016100c9565b9550506020610119888289016100c9565b945050604061012a888289016100c9565b935050606061013b888289016100c9565b925050608061014c888289016100c9565b9150509295509295909350565b61016281610183565b82525050565b600060208201905061017d6000830184610159565b92915050565b6000819050919050565b600061019882610183565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8214156101cb576101ca6101d6565b5b600182019050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600080fd5b61021381610183565b811461021e57600080fd5b5056fea2646970667358221220b98f45f4d4112e71fd287ab0ce7cc1872e53b463eb0abf1182b892192d3d8a1d64736f6c63430008070033' ) tape(`${method}: call with valid arguments`, async (t) => { @@ -55,9 +54,8 @@ tape(`${method}: call with valid arguments`, async (t) => { const contractAddr2 = Address.generate(dummy.addr, BigInt(1)) // construct txs to emit the logs // data calls log(logCount: 10, num1: 1, num2: 2, num3: 3, num4: 4) - const data = Buffer.from( - 'aefb4f0a000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000004', - 'hex' + const data = hexStringToBytes( + 'aefb4f0a000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000004' ) const tx3 = Transaction.fromTxData( { @@ -206,7 +204,7 @@ tape(`${method}: call with valid arguments`, async (t) => { const latestHeader = chain.headers.latest! req = params(method, [ { - blockHash: bufferToHex(latestHeader.hash()), + blockHash: bytesToPrefixedHexString(latestHeader.hash()), }, ]) expectRes = (res: any) => { diff --git a/packages/client/test/rpc/eth/getStorageAt.spec.ts b/packages/client/test/rpc/eth/getStorageAt.spec.ts index ea541afafe..a4374714f5 100644 --- a/packages/client/test/rpc/eth/getStorageAt.spec.ts +++ b/packages/client/test/rpc/eth/getStorageAt.spec.ts @@ -2,7 +2,7 @@ import { Block } from '@ethereumjs/block' import { Blockchain } from '@ethereumjs/blockchain' import { Chain, Common, Hardfork } from '@ethereumjs/common' import { Transaction } from '@ethereumjs/tx' -import { Address, bigIntToHex, bufferToHex, toBuffer } from '@ethereumjs/util' +import { Address, bigIntToHex, bytesToPrefixedHexString, hexStringToBytes } from '@ethereumjs/util' import { keccak256 } from 'ethereum-cryptography/keccak' import * as tape from 'tape' @@ -123,16 +123,13 @@ tape(`${method}: call with valid arguments`, async (t) => { // verify storage of pos1 is accurate // pos1["0xccfd725760a68823ff1e062f4cc97e1360e8d997"] - const key = toBuffer( - keccak256( - Buffer.from( - '000000000000000000000000ccfd725760a68823ff1e062f4cc97e1360e8d997' + - '0000000000000000000000000000000000000000000000000000000000000001', - 'hex' - ) + const key = keccak256( + hexStringToBytes( + '000000000000000000000000ccfd725760a68823ff1e062f4cc97e1360e8d997' + + '0000000000000000000000000000000000000000000000000000000000000001' ) ) - req = params(method, [createdAddress!.toString(), bufferToHex(key), 'latest']) + req = params(method, [createdAddress!.toString(), bytesToPrefixedHexString(key), 'latest']) expectRes = (res: any) => { const msg = 'should return the correct storage value (pos1)' t.equal( diff --git a/packages/client/test/rpc/eth/getTransactionByHash.spec.ts b/packages/client/test/rpc/eth/getTransactionByHash.spec.ts index 92afcc3184..cea1aedfae 100644 --- a/packages/client/test/rpc/eth/getTransactionByHash.spec.ts +++ b/packages/client/test/rpc/eth/getTransactionByHash.spec.ts @@ -1,5 +1,5 @@ import { FeeMarketEIP1559Transaction, Transaction } from '@ethereumjs/tx' -import { bufferToHex } from '@ethereumjs/util' +import { bytesToPrefixedHexString } from '@ethereumjs/util' import * as tape from 'tape' import { @@ -27,16 +27,16 @@ tape(`${method}: call with legacy tx`, async (t) => { await runBlockWithTxs(chain, execution, [tx]) // get the tx - let req = params(method, [bufferToHex(tx.hash())]) + let req = params(method, [bytesToPrefixedHexString(tx.hash())]) let expectRes = (res: any) => { const msg = 'should return the correct tx' - t.equal(res.body.result.hash, bufferToHex(tx.hash()), msg) + t.equal(res.body.result.hash, bytesToPrefixedHexString(tx.hash()), msg) } await baseRequest(t, server, req, 200, expectRes, false) // run a block to ensure tx hash index is cleaned up when txLookupLimit=1 await runBlockWithTxs(chain, execution, []) - req = params(method, [bufferToHex(tx.hash())]) + req = params(method, [bytesToPrefixedHexString(tx.hash())]) expectRes = (res: any) => { const msg = 'should return null when past txLookupLimit' t.equal(res.body.result, null, msg) @@ -65,7 +65,7 @@ tape(`${method}: call with 1559 tx`, async (t) => { await runBlockWithTxs(chain, execution, [tx]) // get the tx - let req = params(method, [bufferToHex(tx.hash())]) + let req = params(method, [bytesToPrefixedHexString(tx.hash())]) let expectRes = (res: any) => { const msg = 'should return the correct tx type' t.equal(res.body.result.type, '0x2', msg) @@ -76,10 +76,10 @@ tape(`${method}: call with 1559 tx`, async (t) => { await runBlockWithTxs(chain, execution, []) await runBlockWithTxs(chain, execution, []) await runBlockWithTxs(chain, execution, []) - req = params(method, [bufferToHex(tx.hash())]) + req = params(method, [bytesToPrefixedHexString(tx.hash())]) expectRes = (res: any) => { const msg = 'should return the correct tx when txLookupLimit=0' - t.equal(res.body.result.hash, bufferToHex(tx.hash()), msg) + t.equal(res.body.result.hash, bytesToPrefixedHexString(tx.hash()), msg) } await baseRequest(t, server, req, 200, expectRes, true) // pass endOnFinish=true for last test }) diff --git a/packages/client/test/rpc/eth/getTransactionReceipt.spec.ts b/packages/client/test/rpc/eth/getTransactionReceipt.spec.ts index f1b182870d..405cf98f3c 100644 --- a/packages/client/test/rpc/eth/getTransactionReceipt.spec.ts +++ b/packages/client/test/rpc/eth/getTransactionReceipt.spec.ts @@ -1,5 +1,5 @@ import { FeeMarketEIP1559Transaction, Transaction } from '@ethereumjs/tx' -import { bufferToHex } from '@ethereumjs/util' +import { bytesToPrefixedHexString } from '@ethereumjs/util' import * as tape from 'tape' import { @@ -31,10 +31,10 @@ tape(`${method}: call with legacy tx`, async (t) => { await runBlockWithTxs(chain, execution, [tx]) // get the tx - const req = params(method, [bufferToHex(tx.hash())]) + const req = params(method, [bytesToPrefixedHexString(tx.hash())]) const expectRes = (res: any) => { const msg = 'should return the correct tx' - t.equal(res.body.result.transactionHash, bufferToHex(tx.hash()), msg) + t.equal(res.body.result.transactionHash, bytesToPrefixedHexString(tx.hash()), msg) } await baseRequest(t, server, req, 200, expectRes) }) @@ -59,10 +59,10 @@ tape(`${method}: call with 1559 tx`, async (t) => { await runBlockWithTxs(chain, execution, [tx]) // get the tx - const req = params(method, [bufferToHex(tx.hash())]) + const req = params(method, [bytesToPrefixedHexString(tx.hash())]) const expectRes = (res: any) => { const msg = 'should return the correct tx' - t.equal(res.body.result.transactionHash, bufferToHex(tx.hash()), msg) + t.equal(res.body.result.transactionHash, bytesToPrefixedHexString(tx.hash()), msg) } await baseRequest(t, server, req, 200, expectRes) }) diff --git a/packages/client/test/rpc/eth/getUncleCountByBlockNumber.spec.ts b/packages/client/test/rpc/eth/getUncleCountByBlockNumber.spec.ts index 47005c2adc..a1f6c68073 100644 --- a/packages/client/test/rpc/eth/getUncleCountByBlockNumber.spec.ts +++ b/packages/client/test/rpc/eth/getUncleCountByBlockNumber.spec.ts @@ -9,7 +9,7 @@ function createChain() { uncleHeaders: ['0x1', '0x2', '0x3'], transactions: [], header: { - hash: () => Buffer.from([1]), + hash: () => new Uint8Array([1]), number: BigInt('5'), }, } diff --git a/packages/client/test/rpc/eth/sendRawTransaction.spec.ts b/packages/client/test/rpc/eth/sendRawTransaction.spec.ts index bd3d877f99..e2b4fe3f38 100644 --- a/packages/client/test/rpc/eth/sendRawTransaction.spec.ts +++ b/packages/client/test/rpc/eth/sendRawTransaction.spec.ts @@ -12,9 +12,8 @@ import { commitmentsToVersionedHashes, getBlobs, } from '@ethereumjs/tx/dist/utils/blobHelpers' -import { toBuffer } from '@ethereumjs/util' +import { bytesToPrefixedHexString, hexStringToBytes, randomBytes } from '@ethereumjs/util' import * as kzg from 'c-kzg' -import { randomBytes } from 'crypto' import * as tape from 'tape' import { INTERNAL_ERROR, INVALID_PARAMS, PARSE_ERROR } from '../../../lib/rpc/error-code' @@ -46,9 +45,7 @@ tape(`${method}: call with valid arguments`, async (t) => { // Mainnet EIP-1559 tx const txData = '0x02f90108018001018402625a0094cccccccccccccccccccccccccccccccccccccccc830186a0b8441a8451e600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f85bf859940000000000000000000000000000000000000101f842a00000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000060a701a0afb6e247b1c490e284053c87ab5f6b59e219d51f743f7a4d83e400782bc7e4b9a0479a268e0e0acd4de3f1e28e4fac2a6b32a4195e8dfa9d19147abe8807aa6f64' - const transaction = FeeMarketEIP1559Transaction.fromSerializedTx( - Buffer.from(txData.slice(2), 'hex') - ) + const transaction = FeeMarketEIP1559Transaction.fromSerializedTx(hexStringToBytes(txData)) const address = transaction.getSenderAddress() const vm = (client.services.find((s) => s.name === 'eth') as FullEthereumService).execution.vm @@ -82,9 +79,9 @@ tape(`${method}: send local tx with gasprice lower than minimum`, async (t) => { gasLimit: 21000, gasPrice: 0, nonce: 0, - }).sign(Buffer.from('42'.repeat(32), 'hex')) + }).sign(hexStringToBytes('42'.repeat(32))) - const txData = '0x' + transaction.serialize().toString('hex') + const txData = bytesToPrefixedHexString(transaction.serialize()) const req = params(method, [txData]) const expectRes = (res: any) => { @@ -157,14 +154,14 @@ tape(`${method}: call with unsigned tx`, async (t) => { const txData = '0x02f90108018001018402625a0094cccccccccccccccccccccccccccccccccccccccc830186a0b8441a8451e600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f85bf859940000000000000000000000000000000000000101f842a00000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000060a701a0afb6e247b1c490e284053c87ab5f6b59e219d51f743f7a4d83e400782bc7e4b9a0479a268e0e0acd4de3f1e28e4fac2a6b32a4195e8dfa9d19147abe8807aa6f64' const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.London }) - const tx = FeeMarketEIP1559Transaction.fromSerializedTx(toBuffer(txData), { + const tx = FeeMarketEIP1559Transaction.fromSerializedTx(hexStringToBytes(txData), { common, freeze: false, }) ;(tx as any).v = undefined ;(tx as any).r = undefined ;(tx as any).s = undefined - const txHex = '0x' + tx.serialize().toString('hex') + const txHex = bytesToPrefixedHexString(tx.serialize()) const req = params(method, [txHex]) const expectRes = checkError(t, INVALID_PARAMS, 'tx needs to be signed') @@ -192,7 +189,7 @@ tape(`${method}: call with no peers`, async (t) => { // Mainnet EIP-1559 tx const txData = '0x02f90108018001018402625a0094cccccccccccccccccccccccccccccccccccccccc830186a0b8441a8451e600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f85bf859940000000000000000000000000000000000000101f842a00000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000060a701a0afb6e247b1c490e284053c87ab5f6b59e219d51f743f7a4d83e400782bc7e4b9a0479a268e0e0acd4de3f1e28e4fac2a6b32a4195e8dfa9d19147abe8807aa6f64' - const transaction = FeeMarketEIP1559Transaction.fromSerializedTx(toBuffer(txData)) + const transaction = FeeMarketEIP1559Transaction.fromSerializedTx(hexStringToBytes(txData)) const address = transaction.getSenderAddress() const vm = (client.services.find((s) => s.name === 'eth') as FullEthereumService).execution.vm @@ -243,11 +240,10 @@ tape('blob EIP 4844 transaction', async (t) => { const commitments = blobsToCommitments(blobs) const versionedHashes = commitmentsToVersionedHashes(commitments) const proof = kzg.computeAggregateKzgProof(blobs.map((blob) => Uint8Array.from(blob))) - const bufferedHashes = versionedHashes.map((el) => Buffer.from(el)) const pk = randomBytes(32) const tx = BlobEIP4844Transaction.fromTxData( { - versionedHashes: bufferedHashes, + versionedHashes, blobs, kzgCommitments: commitments, kzgProof: proof, @@ -262,7 +258,7 @@ tape('blob EIP 4844 transaction', async (t) => { const replacementTx = BlobEIP4844Transaction.fromTxData( { - versionedHashes: bufferedHashes, + versionedHashes, blobs, kzgCommitments: commitments, kzgProof: proof, @@ -279,8 +275,8 @@ tape('blob EIP 4844 transaction', async (t) => { account.balance = BigInt(0xfffffffffffff) await vm.stateManager.putAccount(tx.getSenderAddress(), account) - const req = params(method, ['0x' + tx.serializeNetworkWrapper().toString('hex')]) - const req2 = params(method, ['0x' + replacementTx.serializeNetworkWrapper().toString('hex')]) + const req = params(method, [bytesToPrefixedHexString(tx.serializeNetworkWrapper())]) + const req2 = params(method, [bytesToPrefixedHexString(replacementTx.serializeNetworkWrapper())]) const expectRes = (res: any) => { t.equal(res.body.error, undefined, 'initial blob transaction accepted') } diff --git a/packages/client/test/rpc/helpers.ts b/packages/client/test/rpc/helpers.ts index ec48e15abb..53325fac28 100644 --- a/packages/client/test/rpc/helpers.ts +++ b/packages/client/test/rpc/helpers.ts @@ -1,7 +1,7 @@ import { BlockHeader } from '@ethereumjs/block' import { Blockchain, parseGethGenesisState } from '@ethereumjs/blockchain' import { Chain as ChainEnum, Common, parseGethGenesis } from '@ethereumjs/common' -import { Address, KECCAK256_RLP } from '@ethereumjs/util' +import { Address, KECCAK256_RLP, hexStringToBytes } from '@ethereumjs/util' import { Server as RPCServer } from 'jayson/promise' import { MemoryLevel } from 'memory-level' @@ -30,7 +30,7 @@ const config: any = {} config.logger = getLogger(config) type StartRPCOpts = { port?: number; wsServer?: boolean } -type WithEngineMiddleware = { jwtSecret: Buffer; unlessFn?: (req: IncomingMessage) => boolean } +type WithEngineMiddleware = { jwtSecret: Uint8Array; unlessFn?: (req: IncomingMessage) => boolean } type createClientArgs = { includeVM: boolean // Instantiates the VM when creating the test client @@ -87,7 +87,7 @@ export function createClient(clientOpts: Partial = {}) { } const clientConfig = { ...defaultClientConfig, ...clientOpts } - chain.getTd = async (_hash: Buffer, _num: bigint) => BigInt(1000) + chain.getTd = async (_hash: Uint8Array, _num: bigint) => BigInt(1000) if ((chain as any)._headers !== undefined) { ;(chain as any)._headers.latest = BlockHeader.fromHeaderData( { withdrawalsRoot: common.isActivatedEIP(4895) ? KECCAK256_RLP : undefined }, @@ -304,6 +304,6 @@ export function gethGenesisStartLondon(gethGenesis: any) { * This address has preallocated balance in file `testdata/geth-genesis/pow.json` */ export const dummy = { - addr: Address.fromString('0xcde098d93535445768e8a2345a2f869139f45641'), - privKey: Buffer.from('5831aac354d13ff96a0c051af0d44c0931c2a20bdacee034ffbaa2354d84f5f8', 'hex'), + addr: new Address(hexStringToBytes('0xcde098d93535445768e8a2345a2f869139f45641')), + privKey: hexStringToBytes('5831aac354d13ff96a0c051af0d44c0931c2a20bdacee034ffbaa2354d84f5f8'), } diff --git a/packages/client/test/rpc/mockBlockchain.ts b/packages/client/test/rpc/mockBlockchain.ts index ea6849fafd..40b04c05c0 100644 --- a/packages/client/test/rpc/mockBlockchain.ts +++ b/packages/client/test/rpc/mockBlockchain.ts @@ -1,6 +1,6 @@ import { Block } from '@ethereumjs/block' import { Transaction } from '@ethereumjs/tx' -import { toBuffer } from '@ethereumjs/util' +import { equalsBytes, toBytes } from '@ethereumjs/util' import { dummy } from './helpers' @@ -10,7 +10,7 @@ export function mockBlockchain(options: any = {}) { options.hash ?? '0x910abca1728c53e8d6df870dd7af5352e974357dc58205dea1676be17ba6becf' const transactions = options.transactions ?? [Transaction.fromTxData({}).sign(dummy.privKey)] const block = { - hash: () => toBuffer(blockHash), + hash: () => toBytes(blockHash), header: { number: BigInt(number), }, @@ -25,7 +25,7 @@ export function mockBlockchain(options: any = {}) { return { blocks: { latest: block }, getBlock: async (val: any) => { - if (Buffer.isBuffer(val) && val.equals(Buffer.alloc(32))) { + if (val instanceof Uint8Array && equalsBytes(val, new Uint8Array(32))) { throw Error } return block diff --git a/packages/client/test/rpc/rpc.spec.ts b/packages/client/test/rpc/rpc.spec.ts index f99b1585e1..8fb6e688a8 100644 --- a/packages/client/test/rpc/rpc.spec.ts +++ b/packages/client/test/rpc/rpc.spec.ts @@ -1,3 +1,4 @@ +import { randomBytes } from '@ethereumjs/util' import { encode } from 'jwt-simple' import * as tape from 'tape' @@ -9,7 +10,7 @@ import type { TAlgorithm } from 'jwt-simple' const request = require('supertest') -const jwtSecret = Buffer.from(Array.from({ length: 32 }, () => Math.round(Math.random() * 255))) +const jwtSecret = randomBytes(32) tape('call JSON-RPC without Content-Type header', (t) => { const server = startRPC({}) diff --git a/packages/client/test/rpc/txpool/content.spec.ts b/packages/client/test/rpc/txpool/content.spec.ts index 4b5ad0619d..4585eaf8bf 100644 --- a/packages/client/test/rpc/txpool/content.spec.ts +++ b/packages/client/test/rpc/txpool/content.spec.ts @@ -2,7 +2,7 @@ import { Block, BlockHeader } from '@ethereumjs/block' import { Blockchain } from '@ethereumjs/blockchain' import { Chain, Common, Hardfork } from '@ethereumjs/common' import { TransactionFactory } from '@ethereumjs/tx' -import { randomBytes } from 'crypto' +import { randomBytes } from '@ethereumjs/util' import * as tape from 'tape' import { baseRequest, createClient, createManager, params, startRPC } from '../helpers' diff --git a/packages/client/test/rpc/validation.spec.ts b/packages/client/test/rpc/validation.spec.ts index 88523e57d5..2c562d6923 100644 --- a/packages/client/test/rpc/validation.spec.ts +++ b/packages/client/test/rpc/validation.spec.ts @@ -1,5 +1,4 @@ -import { bufferToHex } from '@ethereumjs/util' -import { randomBytes } from 'crypto' +import { bytesToHex, bytesToPrefixedHexString, randomBytes } from '@ethereumjs/util' import * as tape from 'tape' import { INVALID_PARAMS } from '../../lib/rpc/error-code' @@ -209,7 +208,7 @@ tape(`${prefix} byteVectors`, (t) => { } t.test('Bytes8', (st) => { // valid - st.ok(validatorResult(validators.bytes8([bufferToHex(randomBytes(8))], 0))) + st.ok(validatorResult(validators.bytes8([bytesToPrefixedHexString(randomBytes(8))], 0))) st.ok(validatorResult(validators.bytes8([bytes(8)], 0))) st.ok(validatorResult(validators.bytes8([bytes(1)], 0))) st.ok(validatorResult(validators.bytes8([bytes(2)], 0))) @@ -217,12 +216,12 @@ tape(`${prefix} byteVectors`, (t) => { // invalid st.notOk(validatorResult(validators.bytes8([bytes(10)], 0))) st.notOk(validatorResult(validators.bytes8([bytes(8, false)], 0))) - st.notOk(validatorResult(validators.bytes8([randomBytes(8).toString('hex')], 0))) + st.notOk(validatorResult(validators.bytes8([bytesToHex(randomBytes(8))], 0))) st.end() }) t.test('Uint64', (st) => { // valid - st.ok(validatorResult(validators.uint64([bufferToHex(randomBytes(8))], 0))) + st.ok(validatorResult(validators.uint64([bytesToPrefixedHexString(randomBytes(8))], 0))) st.ok(validatorResult(validators.uint64([bytes(8)], 0))) st.ok(validatorResult(validators.uint64([bytes(1)], 0))) st.ok(validatorResult(validators.uint64([bytes(2)], 0))) @@ -232,12 +231,12 @@ tape(`${prefix} byteVectors`, (t) => { st.notOk(validatorResult(validators.bytes8([badhex(8)], 0))) st.notOk(validatorResult(validators.uint64([bytes(10)], 0))) st.notOk(validatorResult(validators.uint64([bytes(8, false)], 0))) - st.notOk(validatorResult(validators.uint64([randomBytes(8).toString('hex')], 0))) + st.notOk(validatorResult(validators.uint64([bytesToHex(randomBytes(8))], 0))) st.end() }) t.test('Bytes16', (st) => { // valid - st.ok(validatorResult(validators.bytes16([bufferToHex(randomBytes(16))], 0))) + st.ok(validatorResult(validators.bytes16([bytesToPrefixedHexString(randomBytes(16))], 0))) st.ok(validatorResult(validators.bytes16([bytes(16)], 0))) st.ok(validatorResult(validators.bytes16([bytes(1)], 0))) st.ok(validatorResult(validators.bytes16([bytes(2)], 0))) @@ -247,25 +246,25 @@ tape(`${prefix} byteVectors`, (t) => { st.notOk(validatorResult(validators.bytes16([badhex(16)], 0))) st.notOk(validatorResult(validators.bytes16([bytes(20)], 0))) st.notOk(validatorResult(validators.bytes16([bytes(16, false)], 0))) - st.notOk(validatorResult(validators.bytes16([randomBytes(16).toString('hex')], 0))) + st.notOk(validatorResult(validators.bytes16([bytesToHex(randomBytes(16))], 0))) st.end() }) t.test('Bytes20', (st) => { // valid st.ok(validatorResult(validators.bytes20([bytes(20)], 0))) - st.ok(validatorResult(validators.bytes20([bufferToHex(randomBytes(20))], 0))) + st.ok(validatorResult(validators.bytes20([bytesToPrefixedHexString(randomBytes(20))], 0))) st.ok(validatorResult(validators.bytes20([bytes(8)], 0))) st.ok(validatorResult(validators.bytes20([bytes(16)], 0))) // invalid st.notOk(validatorResult(validators.bytes20([badhex(20)], 0))) st.notOk(validatorResult(validators.bytes20([bytes(20, false)], 0))) st.notOk(validatorResult(validators.bytes20([bytes(32)], 0))) - st.notOk(validatorResult(validators.bytes20([randomBytes(20).toString('hex')], 0))) + st.notOk(validatorResult(validators.bytes20([bytesToHex(randomBytes(20))], 0))) st.end() }) t.test('Bytes32', (st) => { // valid - st.ok(validatorResult(validators.bytes32([bufferToHex(randomBytes(32))], 0))) + st.ok(validatorResult(validators.bytes32([bytesToPrefixedHexString(randomBytes(32))], 0))) st.ok(validatorResult(validators.bytes32([bytes(32)], 0))) st.ok(validatorResult(validators.bytes32([bytes(8)], 0))) st.ok(validatorResult(validators.bytes32([bytes(16)], 0))) @@ -274,12 +273,12 @@ tape(`${prefix} byteVectors`, (t) => { st.notOk(validatorResult(validators.bytes32([badhex(32)], 0))) st.notOk(validatorResult(validators.bytes32([bytes(48)], 0))) st.notOk(validatorResult(validators.bytes32([bytes(32, false)], 0))) - st.notOk(validatorResult(validators.bytes32([randomBytes(32).toString('hex')], 0))) + st.notOk(validatorResult(validators.bytes32([bytesToHex(randomBytes(32))], 0))) st.end() }) t.test('Uint256', (st) => { // valid - st.ok(validatorResult(validators.uint256([bufferToHex(randomBytes(32))], 0))) + st.ok(validatorResult(validators.uint256([bytesToPrefixedHexString(randomBytes(32))], 0))) st.ok(validatorResult(validators.uint256([bytes(32)], 0))) st.ok(validatorResult(validators.uint256([bytes(8)], 0))) st.ok(validatorResult(validators.uint256([bytes(16)], 0))) @@ -288,12 +287,12 @@ tape(`${prefix} byteVectors`, (t) => { st.notOk(validatorResult(validators.uint256([badhex(32)], 0))) st.notOk(validatorResult(validators.uint256([bytes(48)], 0))) st.notOk(validatorResult(validators.uint256([bytes(32, false)], 0))) - st.notOk(validatorResult(validators.uint256([randomBytes(32).toString('hex')], 0))) + st.notOk(validatorResult(validators.uint256([bytesToHex(randomBytes(32))], 0))) st.end() }) t.test('Bytes48', (st) => { // valid - st.ok(validatorResult(validators.bytes48([bufferToHex(randomBytes(48))], 0))) + st.ok(validatorResult(validators.bytes48([bytesToPrefixedHexString(randomBytes(48))], 0))) st.ok(validatorResult(validators.bytes48([bytes(48)], 0))) st.ok(validatorResult(validators.bytes48([bytes(8)], 0))) st.ok(validatorResult(validators.bytes48([bytes(16)], 0))) @@ -304,12 +303,12 @@ tape(`${prefix} byteVectors`, (t) => { st.notOk(validatorResult(validators.bytes48([badhex(48)], 0))) st.notOk(validatorResult(validators.bytes48([bytes(64)], 0))) st.notOk(validatorResult(validators.bytes48([bytes(48, false)], 0))) - st.notOk(validatorResult(validators.bytes48([randomBytes(48).toString('hex')], 0))) + st.notOk(validatorResult(validators.bytes48([bytesToHex(randomBytes(48))], 0))) st.end() }) t.test('Bytes256', (st) => { // valid - st.ok(validatorResult(validators.bytes256([bufferToHex(randomBytes(256))], 0))) + st.ok(validatorResult(validators.bytes256([bytesToPrefixedHexString(randomBytes(256))], 0))) st.ok(validatorResult(validators.bytes256([bytes(256)], 0))) st.ok(validatorResult(validators.bytes256([bytes(8)], 0))) st.ok(validatorResult(validators.bytes256([bytes(16)], 0))) @@ -321,7 +320,7 @@ tape(`${prefix} byteVectors`, (t) => { st.notOk(validatorResult(validators.bytes256([badhex(256)], 0))) st.notOk(validatorResult(validators.bytes256([bytes(512)], 0))) st.notOk(validatorResult(validators.bytes256([bytes(256, false)], 0))) - st.notOk(validatorResult(validators.bytes256([randomBytes(256).toString('hex')], 0))) + st.notOk(validatorResult(validators.bytes256([bytesToHex(randomBytes(256))], 0))) st.end() }) diff --git a/packages/client/test/rpc/websocket.spec.ts b/packages/client/test/rpc/websocket.spec.ts index 52d3c5bd4c..0c361d734c 100644 --- a/packages/client/test/rpc/websocket.spec.ts +++ b/packages/client/test/rpc/websocket.spec.ts @@ -1,3 +1,4 @@ +import { randomBytes } from '@ethereumjs/util' import { encode } from 'jwt-simple' import * as tape from 'tape' @@ -9,7 +10,7 @@ import type { TAlgorithm } from 'jwt-simple' const request = require('superwstest') -const jwtSecret = Buffer.from(Array.from({ length: 32 }, () => Math.round(Math.random() * 255))) +const jwtSecret = randomBytes(32) const wsPort = 3000 tape('call JSON-RPC auth protected server with valid token', (t) => { diff --git a/packages/client/test/service/fullethereumservice.spec.ts b/packages/client/test/service/fullethereumservice.spec.ts index 96de836797..0bbe155f7a 100644 --- a/packages/client/test/service/fullethereumservice.spec.ts +++ b/packages/client/test/service/fullethereumservice.spec.ts @@ -1,6 +1,7 @@ import { Common, Hardfork } from '@ethereumjs/common' import { TransactionFactory } from '@ethereumjs/tx' -import { randomBytes } from 'crypto' +import { hexStringToBytes, randomBytes } from '@ethereumjs/util' +import { equalsBytes, hexToBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' import * as td from 'testdouble' @@ -227,23 +228,31 @@ tape('[FullEthereumService]', async (t) => { service.execution = { receiptsManager: { getReceipts: td.func() }, } as any - const blockHash = Buffer.alloc(32, 1) + const blockHash = new Uint8Array(32).fill(1) const receipts = [ { status: 1 as 0 | 1, cumulativeBlockGasUsed: BigInt(100), - bitvector: Buffer.alloc(256), + bitvector: new Uint8Array(256), logs: [ - [Buffer.alloc(20), [Buffer.alloc(32), Buffer.alloc(32, 1)], Buffer.alloc(10)], + [ + new Uint8Array(20), + [new Uint8Array(32), new Uint8Array(32).fill(1)], + new Uint8Array(10), + ], ] as Log[], txType: 2, }, { status: 0 as 0 | 1, cumulativeBlockGasUsed: BigInt(1000), - bitvector: Buffer.alloc(256, 1), + bitvector: new Uint8Array(25).fill(1), logs: [ - [Buffer.alloc(20, 1), [Buffer.alloc(32, 1), Buffer.alloc(32, 1)], Buffer.alloc(10)], + [ + new Uint8Array(20).fill(1), + [new Uint8Array(32).fill(1), new Uint8Array(32).fill(1)], + new Uint8Array(10), + ], ] as Log[], txType: 0, }, @@ -285,14 +294,14 @@ tape('[FullEthereumService]', async (t) => { const chain = await Chain.create({ config }) const service = new FullEthereumService({ config, chain }) service.txPool.handleAnnouncedTxHashes = async (msg, _peer, _pool) => { - st.deepEqual(msg[0], Buffer.from('0xabcd', 'hex'), 'handled NewPooledTransactionhashes') + st.deepEqual(msg[0], hexStringToBytes('0xabcd'), 'handled NewPooledTransactionhashes') st.end() } await service.handle( { name: 'NewPooledTransactionHashes', - data: [Buffer.from('0xabcd', 'hex')], + data: [hexToBytes('0xabcd')], }, 'eth', undefined as any @@ -314,7 +323,7 @@ tape('[FullEthereumService]', async (t) => { { eth: { send: (_: string, data: any): any => { - st.ok(data.txs[0].hash().equals(tx.hash()), 'handled getPooledTransactions') + st.ok(equalsBytes(data.txs[0].hash(), tx.hash()), 'handled getPooledTransactions') st.end() }, } as any, diff --git a/packages/client/test/sim/eof.spec.ts b/packages/client/test/sim/eof.spec.ts index 155a3cc223..c2dea486bf 100644 --- a/packages/client/test/sim/eof.spec.ts +++ b/packages/client/test/sim/eof.spec.ts @@ -1,5 +1,5 @@ import { Common } from '@ethereumjs/common' -import { privateToAddress } from '@ethereumjs/util' +import { bytesToPrefixedHexString, hexStringToBytes, privateToAddress } from '@ethereumjs/util' import { Client } from 'jayson/promise' import * as tape from 'tape' @@ -11,8 +11,8 @@ import { waitForELStart, } from './simutils' -const pkey = Buffer.from('ae557af4ceefda559c924516cabf029bedc36b68109bf8d6183fe96e04121f4e', 'hex') -const sender = '0x' + privateToAddress(pkey).toString('hex') +const pkey = hexStringToBytes('ae557af4ceefda559c924516cabf029bedc36b68109bf8d6183fe96e04121f4e') +const sender = bytesToPrefixedHexString(privateToAddress(pkey)) const client = Client.http({ port: 8545 }) const network = 'eof' diff --git a/packages/client/test/sim/mainnet.spec.ts b/packages/client/test/sim/mainnet.spec.ts index feba6dd97c..390e19060a 100644 --- a/packages/client/test/sim/mainnet.spec.ts +++ b/packages/client/test/sim/mainnet.spec.ts @@ -1,5 +1,5 @@ import { Common } from '@ethereumjs/common' -import { privateToAddress } from '@ethereumjs/util' +import { bytesToPrefixedHexString, hexStringToBytes, privateToAddress } from '@ethereumjs/util' import { Client } from 'jayson/promise' import * as tape from 'tape' @@ -12,8 +12,8 @@ import { waitForELStart, } from './simutils' -const pkey = Buffer.from('ae557af4ceefda559c924516cabf029bedc36b68109bf8d6183fe96e04121f4e', 'hex') -const sender = '0x' + privateToAddress(pkey).toString('hex') +const pkey = hexStringToBytes('ae557af4ceefda559c924516cabf029bedc36b68109bf8d6183fe96e04121f4e') +const sender = bytesToPrefixedHexString(privateToAddress(pkey)) const client = Client.http({ port: 8545 }) const network = 'mainnet' diff --git a/packages/client/test/sim/sharding.spec.ts b/packages/client/test/sim/sharding.spec.ts index 7664da5459..7393bf018a 100644 --- a/packages/client/test/sim/sharding.spec.ts +++ b/packages/client/test/sim/sharding.spec.ts @@ -1,6 +1,6 @@ import { Common } from '@ethereumjs/common' import { TransactionFactory } from '@ethereumjs/tx' -import { privateToAddress } from '@ethereumjs/util' +import { bytesToPrefixedHexString, hexStringToBytes, privateToAddress } from '@ethereumjs/util' import { Client } from 'jayson/promise' import * as tape from 'tape' @@ -15,8 +15,8 @@ import { waitForELStart, } from './simutils' -const pkey = Buffer.from('45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8', 'hex') -const sender = '0x' + privateToAddress(pkey).toString('hex') +const pkey = hexStringToBytes('45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8') +const sender = bytesToPrefixedHexString(privateToAddress(pkey)) const client = Client.http({ port: 8545 }) const network = 'sharding' @@ -89,7 +89,7 @@ tape('sharding/eip4844 hardfork tests', async (t) => { st.equal( eth2kzgs[0], - '0x' + txResult.tx.kzgCommitments![0].toString('hex'), + bytesToPrefixedHexString(txResult.tx.kzgCommitments![0]), 'found expected blob commitments on CL' ) st.end() @@ -136,9 +136,8 @@ tape('sharding/eip4844 hardfork tests', async (t) => { */ const txData = { - data: Buffer.from( - 'f9031103830186a0830f42408080b902c0608060405234801561001057600080fd5b50604051610260380380610260833981810160405281019061003291906101ca565b60008060c0835160145afa61004657600080fd5b50610213565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6100b38261006a565b810181811067ffffffffffffffff821117156100d2576100d161007b565b5b80604052505050565b60006100e561004c565b90506100f182826100aa565b919050565b600067ffffffffffffffff8211156101115761011061007b565b5b61011a8261006a565b9050602081019050919050565b60005b8381101561014557808201518184015260208101905061012a565b83811115610154576000848401525b50505050565b600061016d610168846100f6565b6100db565b90508281526020810184848401111561018957610188610065565b5b610194848285610127565b509392505050565b600082601f8301126101b1576101b0610060565b5b81516101c184826020860161015a565b91505092915050565b6000602082840312156101e0576101df610056565b5b600082015167ffffffffffffffff8111156101fe576101fd61005b565b5b61020a8482850161019c565b91505092915050565b603f806102216000396000f3fe6080604052600080fdfea2646970667358221220cbb964afe0f584a89b887bf992e18697c0ebd77a40a102c121f54213f23d4d9464736f6c634300080f00330000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000212340000000000000000000000000000000000000000000000000000000000001ba002e89a44a4e4da739fed1ed658079a75dbcb59eebbd8ea0cb11f88a41d611dfaa025fe1645a1d3c9828be471fac5cd3e4be59c90ea304c94d774ff88c84349d8db', - 'hex' + data: hexStringToBytes( + 'f9031103830186a0830f42408080b902c0608060405234801561001057600080fd5b50604051610260380380610260833981810160405281019061003291906101ca565b60008060c0835160145afa61004657600080fd5b50610213565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6100b38261006a565b810181811067ffffffffffffffff821117156100d2576100d161007b565b5b80604052505050565b60006100e561004c565b90506100f182826100aa565b919050565b600067ffffffffffffffff8211156101115761011061007b565b5b61011a8261006a565b9050602081019050919050565b60005b8381101561014557808201518184015260208101905061012a565b83811115610154576000848401525b50505050565b600061016d610168846100f6565b6100db565b90508281526020810184848401111561018957610188610065565b5b610194848285610127565b509392505050565b600082601f8301126101b1576101b0610060565b5b81516101c184826020860161015a565b91505092915050565b6000602082840312156101e0576101df610056565b5b600082015167ffffffffffffffff8111156101fe576101fd61005b565b5b61020a8482850161019c565b91505092915050565b603f806102216000396000f3fe6080604052600080fdfea2646970667358221220cbb964afe0f584a89b887bf992e18697c0ebd77a40a102c121f54213f23d4d9464736f6c634300080f00330000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000212340000000000000000000000000000000000000000000000000000000000001ba002e89a44a4e4da739fed1ed658079a75dbcb59eebbd8ea0cb11f88a41d611dfaa025fe1645a1d3c9828be471fac5cd3e4be59c90ea304c94d774ff88c84349d8db' ), nonce: BigInt(nonce.result), gasLimit: 0xffffff, @@ -150,7 +149,7 @@ tape('sharding/eip4844 hardfork tests', async (t) => { const txResult = await client.request( 'eth_sendRawTransaction', - ['0x' + tx.serialize().toString('hex')], + [bytesToPrefixedHexString(tx.serialize())], 2.0 ) let receipt = await client.request('eth_getTransactionReceipt', [txResult.result], 2.0) diff --git a/packages/client/test/sim/simutils.ts b/packages/client/test/sim/simutils.ts index 24e885132f..4efe3d3d7a 100644 --- a/packages/client/test/sim/simutils.ts +++ b/packages/client/test/sim/simutils.ts @@ -5,9 +5,14 @@ import { commitmentsToVersionedHashes, getBlobs, } from '@ethereumjs/tx/dist/utils/blobHelpers' -import { Address } from '@ethereumjs/util' +import { + Address, + bytesToHex, + bytesToPrefixedHexString, + bytesToUtf8, + randomBytes, +} from '@ethereumjs/util' import * as kzg from 'c-kzg' -import { randomBytes } from 'crypto' import * as fs from 'fs/promises' import { Level } from 'level' import { execSync, spawn } from 'node:child_process' @@ -133,7 +138,7 @@ export function runNetwork( const runProcPrefix = withPeer !== undefined ? 'peer1' : '' let lastPrintedDot = false runProc.stdout.on('data', (chunk) => { - const str = Buffer.from(chunk).toString('utf8') + const str = bytesToUtf8(chunk) const filterStr = filterKeywords.reduce((acc, next) => acc || str.includes(next), false) const filterOutStr = filterOutWords.reduce((acc, next) => acc || str.includes(next), false) if (filterStr && !filterOutStr) { @@ -143,16 +148,16 @@ export function runNetwork( } process.stdout.write(`data:${runProcPrefix}: ${runProc.pid}: ${str}`) // str already contains a new line. console.log adds a new line } else { - if (str.includes('Synchronized')) { + if (str.includes('Synchronized') === true) { process.stdout.write('.') lastPrintedDot = true - } else if (str.includes('Synced') && !str.includes('skipped')) { + } else if (str.includes('Synced') === true && str.includes('skipped') === false) { process.stdout.write('`') } } }) runProc.stderr.on('data', (chunk) => { - const str = Buffer.from(chunk).toString('utf8') + const str = bytesToUtf8(chunk) const filterStr = filterKeywords.reduce((acc, next) => acc || str.includes(next), false) const filterOutStr = filterOutWords.reduce((acc, next) => acc || str.includes(next), false) if (filterStr && !filterOutStr) { @@ -178,7 +183,7 @@ export function runNetwork( let lastPrintedDot = false peerRunProc.stdout.on('data', (chunk) => { - const str = Buffer.from(chunk).toString('utf8') + const str = bytesToUtf8(chunk) const filterStr = filterKeywords.reduce((acc, next) => acc || str.includes(next), false) const filterOutStr = filterOutWords.reduce((acc, next) => acc || str.includes(next), false) if (filterStr && !filterOutStr) { @@ -188,14 +193,14 @@ export function runNetwork( } process.stdout.write(`${withPeer}:el<>cl: ${runProc.pid}: ${str}`) // str already contains a new line. console.log adds a new line } else { - if (str.includes('Synchronized')) { + if (str.includes('Synchronized') === true) { process.stdout.write('.') lastPrintedDot = true } } }) peerRunProc.stderr.on('data', (chunk) => { - const str = Buffer.from(chunk).toString('utf8') + const str = bytesToUtf8(chunk) const filterOutStr = filterOutWords.reduce((acc, next) => acc || str.includes(next), false) if (!filterOutStr) { process.stderr.write(`${withPeer}:el<>cl: ${runProc.pid}: ${str}`) // str already contains a new line. console.log adds a new line @@ -241,7 +246,7 @@ export async function startNetwork( } export async function runTxHelper( - opts: { client: Client; common: Common; sender: string; pkey: Buffer }, + opts: { client: Client; common: Common; sender: string; pkey: Uint8Array }, data: string, to?: string, value?: bigint @@ -267,7 +272,7 @@ export async function runTxHelper( const res = await client.request( 'eth_sendRawTransaction', - ['0x' + tx.serialize().toString('hex')], + [bytesToPrefixedHexString(tx.serialize())], 2.0 ) let mined = false @@ -290,11 +295,11 @@ export async function runTxHelper( export const runBlobTx = async ( client: Client, blobSize: number, - pkey: Buffer, + pkey: Uint8Array, to?: string, value?: bigint ) => { - const blobs = getBlobs(randomBytes(blobSize).toString('hex')) + const blobs = getBlobs(bytesToHex(randomBytes(blobSize))) const commitments = blobsToCommitments(blobs) const hashes = commitmentsToVersionedHashes(commitments) @@ -328,7 +333,7 @@ export const runBlobTx = async ( const res = await client.request( 'eth_sendRawTransaction', - ['0x' + serializedWrapper.toString('hex')], + [bytesToPrefixedHexString(serializedWrapper)], 2.0 ) @@ -352,13 +357,13 @@ export const runBlobTx = async ( export const createBlobTxs = async ( numTxs: number, blobSize = 2 ** 17 - 1, - pkey: Buffer, + pkey: Uint8Array, to?: string, value?: bigint ) => { const txHashes: any = [] - const blobs = getBlobs(randomBytes(blobSize).toString('hex')) + const blobs = getBlobs(bytesToHex(randomBytes(blobSize))) const commitments = blobsToCommitments(blobs) const hashes = commitmentsToVersionedHashes(commitments) @@ -389,8 +394,8 @@ export const createBlobTxs = async ( const blobTx = BlobEIP4844Transaction.fromTxData(txData).sign(pkey) const serializedWrapper = blobTx.serializeNetworkWrapper() - await fs.appendFile('./blobs.txt', '0x' + serializedWrapper.toString('hex') + '\n') - txHashes.push('0x' + blobTx.hash().toString('hex')) + await fs.appendFile('./blobs.txt', bytesToPrefixedHexString(serializedWrapper) + '\n') + txHashes.push(bytesToPrefixedHexString(blobTx.hash())) } return txHashes } @@ -409,13 +414,13 @@ export const runBlobTxsFromFile = async (client: Client, path: string) => { export async function createInlineClient(config: any, common: any, customGenesisState: any) { config.events.setMaxListeners(50) const datadir = Config.DATADIR_DEFAULT - const chainDB = new Level( + const chainDB = new Level( `${datadir}/${common.chainName()}/chainDB` ) - const stateDB = new Level( + const stateDB = new Level( `${datadir}/${common.chainName()}/stateDB` ) - const metaDB = new Level( + const metaDB = new Level( `${datadir}/${common.chainName()}/metaDB` ) diff --git a/packages/client/test/sim/snapsync.spec.ts b/packages/client/test/sim/snapsync.spec.ts index 3a032b23c5..aa6f8f6278 100644 --- a/packages/client/test/sim/snapsync.spec.ts +++ b/packages/client/test/sim/snapsync.spec.ts @@ -2,6 +2,7 @@ import { parseGethGenesisState } from '@ethereumjs/blockchain' import { Common } from '@ethereumjs/common' import { privateToAddress } from '@ethereumjs/util' import debug from 'debug' +import { bytesToHex, hexToBytes } from 'ethereum-cryptography/utils' import { Client } from 'jayson/promise' import * as tape from 'tape' @@ -21,8 +22,8 @@ import { import type { EthereumClient } from '../../lib/client' import type { RlpxServer } from '../../lib/net/server' -const pkey = Buffer.from('ae557af4ceefda559c924516cabf029bedc36b68109bf8d6183fe96e04121f4e', 'hex') -const sender = '0x' + privateToAddress(pkey).toString('hex') +const pkey = hexToBytes('ae557af4ceefda559c924516cabf029bedc36b68109bf8d6183fe96e04121f4e') +const sender = '0x' + bytesToHex(privateToAddress(pkey)) const client = Client.http({ port: 8545 }) const network = 'mainnet' diff --git a/packages/client/test/sim/txGenerator.ts b/packages/client/test/sim/txGenerator.ts index 60b32585d4..9f2985c648 100644 --- a/packages/client/test/sim/txGenerator.ts +++ b/packages/client/test/sim/txGenerator.ts @@ -4,9 +4,8 @@ import { blobsToCommitments, commitmentsToVersionedHashes, } from '@ethereumjs/tx/test/utils/blobHelpers' -import { Address } from '@ethereumjs/util' +import { Address, bytesToPrefixedHexString, hexStringToBytes, randomBytes } from '@ethereumjs/util' import * as kzg from 'c-kzg' -import { randomBytes } from 'crypto' import { Client } from 'jayson/promise' const clientPort = process.argv[2] const input = process.argv[3] @@ -19,12 +18,12 @@ const MAX_USEFUL_BYTES_PER_TX = USEFUL_BYTES_PER_BLOB * MAX_BLOBS_PER_TX - 1 const BLOB_SIZE = BYTES_PER_FIELD_ELEMENT * FIELD_ELEMENTS_PER_BLOB initKZG(kzg, __dirname + '/../../lib/trustedSetup/devnet4.txt') -const pkey = Buffer.from('45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8', 'hex') +const pkey = hexStringToBytes('45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8') const sender = Address.fromPrivateKey(pkey) function get_padded(data: any, blobs_len: number) { - const pdata = Buffer.alloc(blobs_len * USEFUL_BYTES_PER_BLOB) - const datalen = Buffer.byteLength(data) + const pdata = new Uint8Array(blobs_len * USEFUL_BYTES_PER_BLOB) + const datalen = (data as Uint8Array).byteLength pdata.fill(data, 0, datalen) // TODO: if data already fits in a pad, then ka-boom pdata[datalen] = 0x80 @@ -32,11 +31,11 @@ function get_padded(data: any, blobs_len: number) { } function get_blob(data: any) { - const blob = Buffer.alloc(BLOB_SIZE, 'binary') + const blob = new Uint8Array(BLOB_SIZE) for (let i = 0; i < FIELD_ELEMENTS_PER_BLOB; i++) { - const chunk = Buffer.alloc(32, 'binary') + const chunk = new Uint8Array(32) chunk.fill(data.subarray(i * 31, (i + 1) * 31), 0, 31) - blob.fill(chunk, i * 32, (i + 1) * 32) + blob.fill(chunk as any, i * 32, (i + 1) * 32) } return blob @@ -44,8 +43,8 @@ function get_blob(data: any) { // ref: https://github.com/asn-d6/blobbers/blob/packing_benchmarks/src/packer_naive.rs function get_blobs(data: any) { - data = Buffer.from(data, 'binary') - const len = Buffer.byteLength(data) + data = hexStringToBytes(data) + const len = (data as Uint8Array).byteLength if (len === 0) { throw Error('invalid blob data') } @@ -57,7 +56,7 @@ function get_blobs(data: any) { const pdata = get_padded(data, blobs_len) - const blobs: Buffer[] = [] + const blobs: Uint8Array[] = [] for (let i = 0; i < blobs_len; i++) { const chunk = pdata.subarray(i * USEFUL_BYTES_PER_BLOB, (i + 1) * USEFUL_BYTES_PER_BLOB) const blob = get_blob(chunk) @@ -123,7 +122,7 @@ async function run(data: any) { const res = await client.request( 'eth_sendRawTransaction', - ['0x' + serializedWrapper.toString('hex')], + [bytesToPrefixedHexString(serializedWrapper)], 2.0 ) @@ -165,8 +164,8 @@ async function run(data: any) { return false } - const expected_kzgs = '0x' + blobTx.kzgCommitments![0].toString('hex') - if (blob_kzg !== '0x' + blobTx.kzgCommitments![0].toString('hex')) { + const expected_kzgs = bytesToPrefixedHexString(blobTx.kzgCommitments![0]) + if (blob_kzg !== bytesToPrefixedHexString(blobTx.kzgCommitments![0])) { console.log(`Unexpected KZG commitment: expected ${expected_kzgs}, got ${blob_kzg}`) return false } else { diff --git a/packages/client/test/sync/beaconsync.spec.ts b/packages/client/test/sync/beaconsync.spec.ts index 85f8517277..c9be394c3f 100644 --- a/packages/client/test/sync/beaconsync.spec.ts +++ b/packages/client/test/sync/beaconsync.spec.ts @@ -127,7 +127,7 @@ tape('[BeaconSynchronizer]', async (t) => { td.when(sync.best()).thenResolve('peer') td.when(sync.latest('peer' as any)).thenResolve({ number: BigInt(2), - hash: () => Buffer.from([]), + hash: () => new Uint8Array(0), }) td.when(ReverseBlockFetcher.prototype.fetch(), { delay: 100, times: 3 }).thenResolve(undefined) ;(skeleton as any).status.progress.subchains = [ @@ -178,7 +178,7 @@ tape('[BeaconSynchronizer]', async (t) => { td.when(sync.best()).thenResolve('peer') td.when(sync.latest('peer' as any)).thenResolve({ number: BigInt(2), - hash: () => Buffer.from([]), + hash: () => new Uint8Array(0), }) td.when(ReverseBlockFetcher.prototype.fetch(), { delay: 100, times: 1 }).thenResolve(undefined) ;(skeleton as any).status.progress.subchains = [{ head: BigInt(10), tail: BigInt(6) }] diff --git a/packages/client/test/sync/fetcher/accountfetcher.spec.ts b/packages/client/test/sync/fetcher/accountfetcher.spec.ts index 0eda934964..719b41c560 100644 --- a/packages/client/test/sync/fetcher/accountfetcher.spec.ts +++ b/packages/client/test/sync/fetcher/accountfetcher.spec.ts @@ -1,5 +1,5 @@ import { RLP } from '@ethereumjs/rlp' -import { bufferToBigInt } from '@ethereumjs/util' +import { bytesToBigInt, hexStringToBytes } from '@ethereumjs/util' import * as tape from 'tape' import * as td from 'testdouble' @@ -30,7 +30,7 @@ tape('[AccountFetcher]', async (t) => { const fetcher = new AccountFetcher({ config, pool, - root: Buffer.from(''), + root: new Uint8Array(0), first: BigInt(1), count: BigInt(10), }) @@ -52,28 +52,28 @@ tape('[AccountFetcher]', async (t) => { const fetcher = new AccountFetcher({ config, pool, - root: Buffer.from(''), + root: new Uint8Array(0), first: BigInt(1), count: BigInt(10), }) const fullResult: any = [ { - hash: Buffer.from(''), - body: [Buffer.from(''), Buffer.from(''), Buffer.from(''), Buffer.from('')], + hash: new Uint8Array(0), + body: [new Uint8Array(0), new Uint8Array(0), new Uint8Array(0), new Uint8Array(0)], }, { - hash: Buffer.from(''), - body: [Buffer.from(''), Buffer.from(''), Buffer.from(''), Buffer.from('')], + hash: new Uint8Array(0), + body: [new Uint8Array(0), new Uint8Array(0), new Uint8Array(0), new Uint8Array(0)], }, ] const accountDataResponse: any = [ { - hash: Buffer.from(''), - body: [Buffer.from(''), Buffer.from(''), Buffer.from(''), Buffer.from('')], + hash: new Uint8Array(0), + body: [new Uint8Array(0), new Uint8Array(0), new Uint8Array(0), new Uint8Array(0)], }, { - hash: Buffer.from(''), - body: [Buffer.from(''), Buffer.from(''), Buffer.from(''), Buffer.from('')], + hash: new Uint8Array(0), + body: [new Uint8Array(0), new Uint8Array(0), new Uint8Array(0), new Uint8Array(0)], }, ] accountDataResponse.completed = true @@ -88,18 +88,18 @@ tape('[AccountFetcher]', async (t) => { const fetcher = new AccountFetcher({ config, pool, - root: Buffer.from(''), + root: new Uint8Array(0), first: BigInt(1), count: BigInt(10), }) const accountDataResponse: any = [ { - hash: Buffer.from(''), - body: [Buffer.from(''), Buffer.from(''), Buffer.from(''), Buffer.from('')], + hash: new Uint8Array(0), + body: [new Uint8Array(0), new Uint8Array(0), new Uint8Array(0), new Uint8Array(0)], }, { - hash: Buffer.from(''), - body: [Buffer.from(''), Buffer.from(''), Buffer.from(''), Buffer.from('')], + hash: new Uint8Array(0), + body: [new Uint8Array(0), new Uint8Array(0), new Uint8Array(0), new Uint8Array(0)], }, ] accountDataResponse.completed = false @@ -114,8 +114,8 @@ tape('[AccountFetcher]', async (t) => { const remainingAccountData: any = [ { - hash: Buffer.from(''), - body: [Buffer.from(''), Buffer.from(''), Buffer.from(''), Buffer.from('')], + hash: new Uint8Array(0), + body: [new Uint8Array(0), new Uint8Array(0), new Uint8Array(0), new Uint8Array(0)], }, ] remainingAccountData.completed = true @@ -131,19 +131,19 @@ tape('[AccountFetcher]', async (t) => { const fetcher = new AccountFetcher({ config, pool, - root: Buffer.from(''), + root: new Uint8Array(0), first: BigInt(1), count: BigInt(3), }) const partialResult: any = [ [ { - hash: Buffer.from(''), - body: [Buffer.from(''), Buffer.from(''), Buffer.from(''), Buffer.from('')], + hash: new Uint8Array(0), + body: [new Uint8Array(0), new Uint8Array(0), new Uint8Array(0), new Uint8Array(0)], }, { - hash: Buffer.from(''), - body: [Buffer.from(''), Buffer.from(''), Buffer.from(''), Buffer.from('')], + hash: new Uint8Array(0), + body: [new Uint8Array(0), new Uint8Array(0), new Uint8Array(0), new Uint8Array(0)], }, ], ] @@ -158,7 +158,7 @@ tape('[AccountFetcher]', async (t) => { await fetcher.request(job as any) td.verify( job.peer.snap.getAccountRange({ - root: Buffer.from(''), + root: new Uint8Array(0), origin: td.matchers.anything(), limit: td.matchers.anything(), bytes: BigInt(50000), @@ -175,18 +175,18 @@ tape('[AccountFetcher]', async (t) => { const fetcher = new AccountFetcher({ config, pool, - root: Buffer.from('39ed8daab7679c0b1b7cf3667c50108185d4d9d1431c24a1c35f696a58277f8f', 'hex'), - first: bufferToBigInt( - Buffer.from('0000000000000000000000000000000000000000000000000000000000000001', 'hex') + root: hexStringToBytes('39ed8daab7679c0b1b7cf3667c50108185d4d9d1431c24a1c35f696a58277f8f'), + first: bytesToBigInt( + hexStringToBytes('0000000000000000000000000000000000000000000000000000000000000001') ), - count: bufferToBigInt( - Buffer.from('000010c6f7a0b5ed8d36b4c7f34938583621fafc8b0079a2834d26fa3fcc9ea9', 'hex') + count: bytesToBigInt( + hexStringToBytes('000010c6f7a0b5ed8d36b4c7f34938583621fafc8b0079a2834d26fa3fcc9ea9') ), }) t.ok(fetcher.storageFetcher !== undefined, 'storageFetcher should be created') const task = { count: 3, first: BigInt(1) } - const resData = RLP.decode(Buffer.from(_accountRangeRLP, 'hex')) as unknown + const resData = RLP.decode(hexStringToBytes(_accountRangeRLP)) const { accounts, proof } = p.decode( p.messages.filter((message) => message.name === 'AccountRange')[0], resData @@ -252,7 +252,7 @@ tape('[AccountFetcher]', async (t) => { const fetcher = new AccountFetcher({ config, pool, - root: Buffer.from(''), + root: new Uint8Array(0), first: BigInt(1), count: BigInt(10), }) diff --git a/packages/client/test/sync/fetcher/storagefetcher.spec.ts b/packages/client/test/sync/fetcher/storagefetcher.spec.ts index 72a66fb04c..168b2fe0ed 100644 --- a/packages/client/test/sync/fetcher/storagefetcher.spec.ts +++ b/packages/client/test/sync/fetcher/storagefetcher.spec.ts @@ -1,4 +1,5 @@ import { RLP } from '@ethereumjs/rlp' +import { hexToBytes, utf8ToBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' import * as td from 'testdouble' @@ -28,16 +29,14 @@ tape('[StorageFetcher]', async (t) => { const fetcher = new StorageFetcher({ config, pool, - root: Buffer.from('e794e45a596856bcd5412788f46752a559a4aa89fe556ab26a8c2cf0fc24cb5e', 'hex'), + root: hexToBytes('e794e45a596856bcd5412788f46752a559a4aa89fe556ab26a8c2cf0fc24cb5e'), storageRequests: [ { - accountHash: Buffer.from( - '352a47fc6863b89a6b51890ef3c1550d560886c027141d2058ba1e2d4c66d99a', - 'hex' + accountHash: hexToBytes( + '352a47fc6863b89a6b51890ef3c1550d560886c027141d2058ba1e2d4c66d99a' ), - storageRoot: Buffer.from( - '556a482068355939c95a3412bdb21213a301483edb1b64402fb66ac9f3583599', - 'hex' + storageRoot: hexToBytes( + '556a482068355939c95a3412bdb21213a301483edb1b64402fb66ac9f3583599' ), first: BigInt(0), count: BigInt(2) ** BigInt(256) - BigInt(1), @@ -50,14 +49,8 @@ tape('[StorageFetcher]', async (t) => { t.equal((fetcher as any).storageRequests.length, 1, 'one storageRequests have been added') fetcher.enqueueByStorageRequestList([ { - accountHash: Buffer.from( - 'e9a5016cb1a53dbc750d06e725514ac164231d71853cafdcbff42f5adb6ca6f1', - 'hex' - ), - storageRoot: Buffer.from( - '69522138e4770e642ec8d7bd5e2b71a23fb732bb447cd4faf838b45cfe3b2a92', - 'hex' - ), + accountHash: hexToBytes('e9a5016cb1a53dbc750d06e725514ac164231d71853cafdcbff42f5adb6ca6f1'), + storageRoot: hexToBytes('69522138e4770e642ec8d7bd5e2b71a23fb732bb447cd4faf838b45cfe3b2a92'), first: BigInt(0), count: BigInt(2) ** BigInt(256) - BigInt(1), }, @@ -82,33 +75,31 @@ tape('[StorageFetcher]', async (t) => { const fetcher = new StorageFetcher({ config, pool, - root: Buffer.from(''), + root: utf8ToBytes(''), first: BigInt(1), count: BigInt(10), }) const fullResult: any = [ [ - [{ hash: Buffer.from(''), body: Buffer.from('') }], - [{ hash: Buffer.from(''), body: Buffer.from('') }], + [{ hash: utf8ToBytes(''), body: utf8ToBytes('') }], + [{ hash: utf8ToBytes(''), body: utf8ToBytes('') }], ], ] const StorageDataResponse: any = [ [ - [{ hash: Buffer.from(''), body: Buffer.from('') }], - [{ hash: Buffer.from(''), body: Buffer.from('') }], + [{ hash: utf8ToBytes(''), body: utf8ToBytes('') }], + [{ hash: utf8ToBytes(''), body: utf8ToBytes('') }], ], ] StorageDataResponse.completed = true const task = { storageRequests: [ { - accountHash: Buffer.from( - 'e9a5016cb1a53dbc750d06e725514ac164231d71853cafdcbff42f5adb6ca6f1', - 'hex' + accountHash: hexToBytes( + 'e9a5016cb1a53dbc750d06e725514ac164231d71853cafdcbff42f5adb6ca6f1' ), - storageRoot: Buffer.from( - '69522138e4770e642ec8d7bd5e2b71a23fb732bb447cd4faf838b45cfe3b2a92', - 'hex' + storageRoot: hexToBytes( + '69522138e4770e642ec8d7bd5e2b71a23fb732bb447cd4faf838b45cfe3b2a92' ), first: BigInt(0), count: BigInt(2) ** BigInt(256) - BigInt(1), @@ -133,25 +124,23 @@ tape('[StorageFetcher]', async (t) => { const fetcher = new StorageFetcher({ config, pool, - root: Buffer.from(''), + root: utf8ToBytes(''), }) const StorageDataResponse: any = [ [ - [{ hash: Buffer.from(''), body: Buffer.from('') }], - [{ hash: Buffer.from(''), body: Buffer.from('') }], + [{ hash: utf8ToBytes(''), body: utf8ToBytes('') }], + [{ hash: utf8ToBytes(''), body: utf8ToBytes('') }], ], ] StorageDataResponse.completed = false const task = { storageRequests: [ { - accountHash: Buffer.from( - 'e9a5016cb1a53dbc750d06e725514ac164231d71853cafdcbff42f5adb6ca6f1', - 'hex' + accountHash: hexToBytes( + 'e9a5016cb1a53dbc750d06e725514ac164231d71853cafdcbff42f5adb6ca6f1' ), - storageRoot: Buffer.from( - '69522138e4770e642ec8d7bd5e2b71a23fb732bb447cd4faf838b45cfe3b2a92', - 'hex' + storageRoot: hexToBytes( + '69522138e4770e642ec8d7bd5e2b71a23fb732bb447cd4faf838b45cfe3b2a92' ), first: BigInt(0), count: BigInt(2) ** BigInt(256) - BigInt(1), @@ -167,9 +156,9 @@ tape('[StorageFetcher]', async (t) => { t.equal(results, undefined, 'Process should not return full results yet') const remainingStorageData: any = [ [ - [{ hash: Buffer.from(''), body: Buffer.from('') }], - [{ hash: Buffer.from(''), body: Buffer.from('') }], - [{ hash: Buffer.from(''), body: Buffer.from('') }], + [{ hash: utf8ToBytes(''), body: utf8ToBytes('') }], + [{ hash: utf8ToBytes(''), body: utf8ToBytes('') }], + [{ hash: utf8ToBytes(''), body: utf8ToBytes('') }], ], ] remainingStorageData.completed = true @@ -186,32 +175,30 @@ tape('[StorageFetcher]', async (t) => { const fetcher = new StorageFetcher({ config, pool, - root: Buffer.from(''), + root: utf8ToBytes(''), }) const partialResult: any = [ [ - [{ hash: Buffer.from(''), body: Buffer.from('') }], - [{ hash: Buffer.from(''), body: Buffer.from('') }], + [{ hash: utf8ToBytes(''), body: utf8ToBytes('') }], + [{ hash: utf8ToBytes(''), body: utf8ToBytes('') }], ], ] const task = { storageRequests: [ { - accountHash: Buffer.from( - 'e9a5016cb1a53dbc750d06e725514ac164231d71853cafdcbff42f5adb6ca6f1', - 'hex' + accountHash: hexToBytes( + 'e9a5016cb1a53dbc750d06e725514ac164231d71853cafdcbff42f5adb6ca6f1' ), - storageRoot: Buffer.from( - '69522138e4770e642ec8d7bd5e2b71a23fb732bb447cd4faf838b45cfe3b2a92', - 'hex' + storageRoot: hexToBytes( + '69522138e4770e642ec8d7bd5e2b71a23fb732bb447cd4faf838b45cfe3b2a92' ), first: BigInt(0), count: BigInt(2) ** BigInt(256) - BigInt(1), }, ], } - const resData = RLP.decode(Buffer.from(_storageRangesRLP, 'hex')) as unknown + const resData = RLP.decode(hexToBytes(_storageRangesRLP)) as unknown const res = p.decode( p.messages.filter((message) => message.name === 'StorageRanges')[0], resData @@ -232,10 +219,8 @@ tape('[StorageFetcher]', async (t) => { await fetcher.request(job as any) td.verify( job.peer.snap.getStorageRanges({ - root: Buffer.from(''), - accounts: [ - Buffer.from('e9a5016cb1a53dbc750d06e725514ac164231d71853cafdcbff42f5adb6ca6f1', 'hex'), - ], + root: utf8ToBytes(''), + accounts: [hexToBytes('e9a5016cb1a53dbc750d06e725514ac164231d71853cafdcbff42f5adb6ca6f1')], origin: td.matchers.anything(), limit: td.matchers.anything(), bytes: BigInt(50000), @@ -252,32 +237,30 @@ tape('[StorageFetcher]', async (t) => { const fetcher = new StorageFetcher({ config, pool, - root: Buffer.from(''), + root: utf8ToBytes(''), }) const partialResult: any = [ [ - [{ hash: Buffer.from(''), body: Buffer.from('') }], - [{ hash: Buffer.from(''), body: Buffer.from('') }], + [{ hash: utf8ToBytes(''), body: utf8ToBytes('') }], + [{ hash: utf8ToBytes(''), body: utf8ToBytes('') }], ], ] const task = { storageRequests: [ { - accountHash: Buffer.from( - '00009e5969eba9656d7e4dad5b0596241deb87c29bbab71c23b602c2b88a7276', - 'hex' + accountHash: hexToBytes( + '00009e5969eba9656d7e4dad5b0596241deb87c29bbab71c23b602c2b88a7276' ), - storageRoot: Buffer.from( - '4431bd7d69241190bb930b74485c1e31ff75552f67d758d0b6612e7bd9226121', - 'hex' + storageRoot: hexToBytes( + '4431bd7d69241190bb930b74485c1e31ff75552f67d758d0b6612e7bd9226121' ), first: BigInt(0), count: BigInt(2) ** BigInt(256) - BigInt(1), }, ], } - const resData = RLP.decode(Buffer.from(_storageRangesRLP, 'hex')) as unknown + const resData = RLP.decode(hexToBytes(_storageRangesRLP)) as unknown const res = p.decode( p.messages.filter((message) => message.name === 'StorageRanges')[0], resData @@ -315,14 +298,13 @@ tape('[StorageFetcher]', async (t) => { // We have not been able to captured valid storage proof yet but we can try invalid // proof for coverage. A valid proof test can be added later - const accResData = RLP.decode(Buffer.from(_accountRangeRLP, 'hex')) as unknown + const accResData = RLP.decode(hexToBytes(_accountRangeRLP)) as unknown const { proof: proofInvalid } = p.decode( p.messages.filter((message) => message.name === 'AccountRange')[0], accResData ) - const dummyStorageRoot = Buffer.from( - '39ed8daab7679c0b1b7cf3667c50108185d4d9d1431c24a1c35f696a58277f8f', - 'hex' + const dummyStorageRoot = hexToBytes( + '39ed8daab7679c0b1b7cf3667c50108185d4d9d1431c24a1c35f696a58277f8f' ) const dummyOrigin = Buffer.alloc(32) try { @@ -349,7 +331,7 @@ tape('[StorageFetcher]', async (t) => { const fetcher = new StorageFetcher({ config, pool, - root: Buffer.from(''), + root: utf8ToBytes(''), first: BigInt(1), count: BigInt(10), }) diff --git a/packages/client/test/sync/fullsync.spec.ts b/packages/client/test/sync/fullsync.spec.ts index 26c2ace473..eb135fd22a 100644 --- a/packages/client/test/sync/fullsync.spec.ts +++ b/packages/client/test/sync/fullsync.spec.ts @@ -125,7 +125,7 @@ tape('[FullSynchronizer]', async (t) => { td.when(sync.best()).thenResolve('peer') td.when(sync.latest('peer' as any)).thenResolve({ number: BigInt(2), - hash: () => Buffer.from([]), + hash: () => new Uint8Array(0), }) td.when(BlockFetcher.prototype.fetch(), { delay: 20, times: 2 }).thenResolve(undefined) ;(sync as any).chain = { blocks: { height: BigInt(3) } } diff --git a/packages/client/test/sync/lightsync.spec.ts b/packages/client/test/sync/lightsync.spec.ts index 0038390db9..9f5b4f5760 100644 --- a/packages/client/test/sync/lightsync.spec.ts +++ b/packages/client/test/sync/lightsync.spec.ts @@ -76,7 +76,7 @@ tape('[LightSynchronizer]', async (t) => { td.when(sync.best()).thenResolve({ les: { status: { headNum: BigInt(2) } } } as any) td.when(sync.latest(td.matchers.anything())).thenResolve({ number: BigInt(2), - hash: () => Buffer.from([]), + hash: () => new Uint8Array(0), }) td.when(HeaderFetcher.prototype.fetch(), { delay: 20, times: 2 }).thenResolve(undefined) ;(sync as any).chain = { headers: { height: BigInt(3) } } @@ -113,7 +113,7 @@ tape('[LightSynchronizer]', async (t) => { td.when(sync.best()).thenResolve({ les: { status: { headNum: BigInt(2) } } } as any) td.when(sync.latest(td.matchers.anything())).thenResolve({ number: BigInt(2), - hash: () => Buffer.from([]), + hash: () => new Uint8Array(0), }) td.when(HeaderFetcher.prototype.fetch()).thenResolve(undefined) td.when(HeaderFetcher.prototype.fetch()).thenDo(() => @@ -147,7 +147,7 @@ tape('[LightSynchronizer]', async (t) => { td.when(sync.best()).thenResolve({ les: { status: { headNum: BigInt(2) } } } as any) td.when(sync.latest(td.matchers.anything())).thenResolve({ number: BigInt(2), - hash: () => Buffer.from([]), + hash: () => new Uint8Array(0), }) td.when(HeaderFetcher.prototype.fetch()).thenResolve(undefined) td.when(HeaderFetcher.prototype.fetch()).thenDo(() => diff --git a/packages/client/test/sync/skeleton.spec.ts b/packages/client/test/sync/skeleton.spec.ts index 456ac9c411..c8480b3f6a 100644 --- a/packages/client/test/sync/skeleton.spec.ts +++ b/packages/client/test/sync/skeleton.spec.ts @@ -1,5 +1,6 @@ import { Block, BlockHeader } from '@ethereumjs/block' import { Common } from '@ethereumjs/common' +import { equalsBytes, utf8ToBytes } from 'ethereum-cryptography/utils' import { MemoryLevel } from 'memory-level' import * as tape from 'tape' import * as td from 'testdouble' @@ -19,7 +20,7 @@ type Subchain = { const common = new Common({ chain: 1 }) const block49 = Block.fromBlockData({ header: { number: 49 } }, { common }) const block49B = Block.fromBlockData( - { header: { number: 49, extraData: Buffer.from('B') } }, + { header: { number: 49, extraData: utf8ToBytes('B') } }, { common } ) const block50 = Block.fromBlockData( @@ -724,8 +725,9 @@ tape('[Skeleton] / setHead', async (t) => { BigInt(4), 'canonical height should now be at head with correct chain' ) + const latestHash = chain.headers.latest?.hash() st.ok( - chain.headers.latest?.hash().equals(block4PoS.hash()), + latestHash !== undefined && equalsBytes(latestHash, block4PoS.hash()), 'canonical height should now be at head with correct chain' ) await skeleton.setHead(block5, true) @@ -881,8 +883,9 @@ tape('[Skeleton] / setHead', async (t) => { BigInt(3), 'canonical height should now be at head with correct chain' ) + const latestHash = chain.headers.latest?.hash() st.ok( - chain.headers.latest?.hash().equals(block3.hash()), + latestHash !== undefined && equalsBytes(latestHash, block3.hash()), 'canonical height should now be at head with correct chain' ) diff --git a/packages/client/test/sync/sync.spec.ts b/packages/client/test/sync/sync.spec.ts index 0e05dc0d7f..51d3892f6c 100644 --- a/packages/client/test/sync/sync.spec.ts +++ b/packages/client/test/sync/sync.spec.ts @@ -44,7 +44,7 @@ tape('[Synchronizer]', async (t) => { }) void sync.start() ;(sync as any).chain._headers = { - latest: { hash: () => Buffer.from([]), number: BigInt(1) }, + latest: { hash: () => new Uint8Array(0), number: BigInt(1) }, td: BigInt(0), height: BigInt(1), } diff --git a/packages/client/test/sync/txpool.spec.ts b/packages/client/test/sync/txpool.spec.ts index 13116a2fa4..7d46da2b27 100644 --- a/packages/client/test/sync/txpool.spec.ts +++ b/packages/client/test/sync/txpool.spec.ts @@ -2,7 +2,13 @@ import { Block } from '@ethereumjs/block' import { Chain, Common, Hardfork } from '@ethereumjs/common' import { DefaultStateManager } from '@ethereumjs/statemanager' import { AccessListEIP2930Transaction, FeeMarketEIP1559Transaction } from '@ethereumjs/tx' -import { Account, privateToAddress } from '@ethereumjs/util' +import { + Account, + bytesToHex, + concatBytes, + hexStringToBytes, + privateToAddress, +} from '@ethereumjs/util' import * as tape from 'tape' import { Config } from '../../lib/config' @@ -23,7 +29,7 @@ const setup = () => { vm: { stateManager: { getAccount: () => new Account(BigInt(0), BigInt('50000000000000000000')), - setStateRoot: async (_root: Buffer) => {}, + setStateRoot: async (_root: Uint8Array) => {}, }, copy: () => service.execution.vm, }, @@ -48,7 +54,7 @@ const handleTxs = async ( try { if (stateManager !== undefined) { ;(pool).service.execution.vm.stateManager = stateManager - ;(pool).service.execution.vm.stateManager.setStateRoot = async (_root: Buffer) => {} + ;(pool).service.execution.vm.stateManager.setStateRoot = async (_root: Uint8Array) => {} } pool.open() @@ -89,18 +95,16 @@ tape('[TxPool]', async (t) => { DefaultStateManager.prototype.setStateRoot = (): any => {} const A = { - address: Buffer.from('0b90087d864e82a284dca15923f3776de6bb016f', 'hex'), - privateKey: Buffer.from( - '64bf9cc30328b0e42387b3c82c614e6386259136235e20c1357bd11cdee86993', - 'hex' + address: hexStringToBytes('0b90087d864e82a284dca15923f3776de6bb016f'), + privateKey: hexStringToBytes( + '64bf9cc30328b0e42387b3c82c614e6386259136235e20c1357bd11cdee86993' ), } const B = { - address: Buffer.from('6f62d8382bf2587361db73ceca28be91b2acb6df', 'hex'), - privateKey: Buffer.from( - '2a6e9ad5a6a8e4f17149b8bc7128bf090566a11dbd63c30e5a0ee9f161309cd6', - 'hex' + address: hexStringToBytes('6f62d8382bf2587361db73ceca28be91b2acb6df'), + privateKey: hexStringToBytes( + '2a6e9ad5a6a8e4f17149b8bc7128bf090566a11dbd63c30e5a0ee9f161309cd6' ), } @@ -202,15 +206,15 @@ tape('[TxPool]', async (t) => { t.equal((pool as any).knownByPeer.get(peer.id).length, 1, 'one tx added for peer 1') t.equal( (pool as any).knownByPeer.get(peer.id)[0].hash, - txA01.hash().toString('hex'), + bytesToHex(txA01.hash()), 'new known tx hashes entry for announcing peer' ) const txs = pool.getByHash([txA01.hash()]) t.equal(txs.length, 1, 'should get correct number of txs by hash') t.equal( - txs[0].serialize().toString('hex'), - txA01.serialize().toString('hex'), + bytesToHex(txs[0].serialize()), + bytesToHex(txA01.serialize()), 'should get correct tx by hash' ) @@ -247,7 +251,7 @@ tape('[TxPool]', async (t) => { const hashes = [] for (let i = 1; i <= TX_RETRIEVAL_LIMIT + 1; i++) { // One more than TX_RETRIEVAL_LIMIT - hashes.push(Buffer.from(i.toString().padStart(64, '0'), 'hex')) // '0000000000000000000000000000000000000000000000000000000000000001',... + hashes.push(hexStringToBytes(i.toString().padStart(64, '0'))) // '0000000000000000000000000000000000000000000000000000000000000001',... } await pool.handleAnnouncedTxHashes(hashes, peer as any, peerPool) @@ -291,7 +295,7 @@ tape('[TxPool]', async (t) => { await pool.handleAnnouncedTxHashes([txA01.hash(), txA02.hash()], peer, peerPool) t.equal(pool.pool.size, 1, 'pool size 1') - const address = A.address.toString('hex') + const address = bytesToHex(A.address) const poolContent = pool.pool.get(address)! t.equal(poolContent.length, 1, 'only one tx') t.deepEqual(poolContent[0].tx.hash(), txA02.hash(), 'only later-added tx') @@ -336,7 +340,7 @@ tape('[TxPool]', async (t) => { e.message.includes('replacement gas too low'), 'successfully failed adding underpriced txn' ) - const poolObject = pool['handled'].get(txA02_Underpriced.hash().toString('hex')) + const poolObject = pool['handled'].get(bytesToHex(txA02_Underpriced.hash())) t.equal(poolObject?.error, e, 'should have an errored poolObject') const poolTxs = pool.getByHash([txA02_Underpriced.hash()]) t.equal(poolTxs.length, 0, `should not be added in pool`) @@ -349,7 +353,7 @@ tape('[TxPool]', async (t) => { 'NewPooledTransactionHashes', 'should have errored sendObject for NewPooledTransactionHashes broadcast' ) - const address = A.address.toString('hex') + const address = bytesToHex(A.address) const poolContent = pool.pool.get(address)! t.equal(poolContent.length, 1, 'only one tx') t.deepEqual(poolContent[0].tx.hash(), txA01.hash(), 'only later-added tx') @@ -383,7 +387,7 @@ tape('[TxPool]', async (t) => { await pool.handleAnnouncedTxHashes([txA01.hash(), txA02_Underpriced.hash()], peer, peerPool) t.equal(pool.pool.size, 1, 'pool size 1') - const address = A.address.toString('hex') + const address = bytesToHex(A.address) const poolContent = pool.pool.get(address)! t.equal(poolContent.length, 1, 'only one tx') t.deepEqual(poolContent[0].tx.hash(), txA01.hash(), 'only later-added tx') @@ -396,10 +400,10 @@ tape('[TxPool]', async (t) => { // Setup 5001 txs const txs = [] for (let account = 0; account < 51; account++) { - const pkey = Buffer.concat([ - Buffer.from('aa'.repeat(31), 'hex'), - Buffer.from(account.toString(16).padStart(2, '0'), 'hex'), - ]) + const pkey = concatBytes( + hexStringToBytes('aa'.repeat(31)), + hexStringToBytes(account.toString(16).padStart(2, '0')) + ) const from = { address: privateToAddress(pkey), privateKey: pkey, @@ -651,7 +655,7 @@ tape('[TxPool]', async (t) => { await pool.handleAnnouncedTxs([txA01], peer, peerPool) t.equal(pool.pool.size, 1, 'pool size 1') - const address = A.address.toString('hex') + const address = bytesToHex(A.address) const poolContent = pool.pool.get(address)! t.equal(poolContent.length, 1, 'one tx') t.deepEqual(poolContent[0].tx.hash(), txA01.hash(), 'correct tx') @@ -695,7 +699,7 @@ tape('[TxPool]', async (t) => { } await pool.handleAnnouncedTxHashes([txB01.hash(), txB02.hash()], peer, peerPool) t.equal(pool.pool.size, 1, 'pool size 1') - const address = B.address.toString('hex') + const address = bytesToHex(B.address) let poolContent = pool.pool.get(address)! t.equal(poolContent.length, 2, 'two txs') @@ -770,7 +774,7 @@ tape('[TxPool]', async (t) => { knownByPeerObj1.added = Date.now() - pool.POOLED_STORAGE_TIME_LIMIT * 1000 * 60 - 1 ;(pool as any).knownByPeer.set(peer.id, [knownByPeerObj1, knownByPeerObj2]) - const hash = txB01.hash().toString('hex') + const hash = bytesToHex(txB01.hash()) const handledObj = (pool as any).handled.get(hash) handledObj.added = Date.now() - pool.HANDLED_CLEANUP_TIME_LIMIT * 1000 * 60 - 1 ;(pool as any).handled.set(hash, handledObj) diff --git a/packages/client/test/util/rpc.spec.ts b/packages/client/test/util/rpc.spec.ts index c8727d4503..b58c707c01 100644 --- a/packages/client/test/util/rpc.spec.ts +++ b/packages/client/test/util/rpc.spec.ts @@ -1,3 +1,4 @@ +import { bytesToPrefixedHexString } from '@ethereumjs/util' import * as tape from 'tape' import { EthereumClient } from '../../lib/client' @@ -24,14 +25,17 @@ tape('[Util/RPC]', (t) => { const { server } = createRPCServer(manager, { methodConfig, rpcDebug, logger }) const httpServer = createRPCServerListener({ server, - withEngineMiddleware: { jwtSecret: Buffer.alloc(32) }, + withEngineMiddleware: { jwtSecret: new Uint8Array(32) }, }) const wsServer = createWsRPCServerListener({ server, - withEngineMiddleware: { jwtSecret: Buffer.alloc(32) }, + withEngineMiddleware: { jwtSecret: new Uint8Array(32) }, }) const req = { id: 1, method: 'eth_getCanonicalHeadBlock', params: [] } - const resp = { id: 1, result: { test: '0x' + Buffer.alloc(64, 1).toString('hex') } } + const resp = { + id: 1, + result: { test: bytesToPrefixedHexString(new Uint8Array(64).fill(1)) }, + } const reqBulk = [req, req] const respBulk = [resp, { id: 2, error: { err0: '456' } }] // Valid diff --git a/packages/common/src/common.ts b/packages/common/src/common.ts index 57cff62c9f..5c690a05e4 100644 --- a/packages/common/src/common.ts +++ b/packages/common/src/common.ts @@ -1,4 +1,11 @@ -import { TypeOutput, intToBuffer, toType } from '@ethereumjs/util' +import { + TypeOutput, + bytesToHex, + concatBytes, + hexStringToBytes, + intToBytes, + toType, +} from '@ethereumjs/util' import { buf as crc32Buffer } from 'crc-32' import { EventEmitter } from 'events' @@ -828,8 +835,8 @@ export class Common extends EventEmitter { * @param genesisHash Genesis block hash of the chain * @returns Fork hash as hex string */ - _calcForkHash(hardfork: string | Hardfork, genesisHash: Buffer) { - let hfBuffer = Buffer.alloc(0) + _calcForkHash(hardfork: string | Hardfork, genesisHash: Uint8Array) { + let hfBytes = new Uint8Array(0) let prevBlockOrTime = 0 for (const hf of this.hardforks()) { const { block, timestamp, name } = hf @@ -847,18 +854,18 @@ export class Common extends EventEmitter { blockOrTime !== prevBlockOrTime && name !== Hardfork.Merge ) { - const hfBlockBuffer = Buffer.from(blockOrTime.toString(16).padStart(16, '0'), 'hex') - hfBuffer = Buffer.concat([hfBuffer, hfBlockBuffer]) + const hfBlockBytes = hexStringToBytes(blockOrTime.toString(16).padStart(16, '0')) + hfBytes = concatBytes(hfBytes, hfBlockBytes) prevBlockOrTime = blockOrTime } if (hf.name === hardfork) break } - const inputBuffer = Buffer.concat([genesisHash, hfBuffer]) + const inputBytes = concatBytes(genesisHash, hfBytes) // CRC32 delivers result as signed (negative) 32-bit integer, // convert to hex string - const forkhash = intToBuffer(crc32Buffer(inputBuffer) >>> 0).toString('hex') + const forkhash = bytesToHex(intToBytes(crc32Buffer(inputBytes) >>> 0)) return `0x${forkhash}` } @@ -867,7 +874,7 @@ export class Common extends EventEmitter { * @param hardfork Hardfork name, optional if HF set * @param genesisHash Genesis block hash of the chain, optional if already defined and not needed to be calculated */ - forkHash(hardfork?: string | Hardfork, genesisHash?: Buffer): string { + forkHash(hardfork?: string | Hardfork, genesisHash?: Uint8Array): string { hardfork = hardfork ?? this._hardfork const data = this._getHardfork(hardfork) if ( @@ -901,7 +908,7 @@ export class Common extends EventEmitter { * @param common The {@link Common} to set the forkHashes for * @param genesisHash The genesis block hash */ - setForkHashes(genesisHash: Buffer) { + setForkHashes(genesisHash: Uint8Array) { for (const hf of this.hardforks()) { const blockOrTime = hf.timestamp ?? hf.block if ( diff --git a/packages/common/src/types.ts b/packages/common/src/types.ts index 5c6088b8a9..a3e5e437bc 100644 --- a/packages/common/src/types.ts +++ b/packages/common/src/types.ts @@ -117,6 +117,6 @@ export interface CustomCommonOpts extends BaseOpts { export interface GethConfigOpts extends BaseOpts { chain?: string - genesisHash?: Buffer + genesisHash?: Uint8Array mergeForkIdPostMerge?: boolean } diff --git a/packages/common/test/hardforks.spec.ts b/packages/common/test/hardforks.spec.ts index b8c4152cfa..5841faf6bf 100644 --- a/packages/common/test/hardforks.spec.ts +++ b/packages/common/test/hardforks.spec.ts @@ -1,3 +1,4 @@ +import { hexStringToBytes } from '@ethereumjs/util' import * as tape from 'tape' import { Chain, Common, ConsensusAlgorithm, ConsensusType, Hardfork } from '../src' @@ -270,26 +271,26 @@ tape('[Common]: Hardfork logic', function (t: tape.Test) { }) t.test('_calcForkHash()', function (st: tape.Test) { - const chains: [Chain, Buffer][] = [ + const chains: [Chain, Uint8Array][] = [ [ Chain.Mainnet, - Buffer.from('d4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3', 'hex'), + hexStringToBytes('d4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3'), ], [ Chain.Ropsten, - Buffer.from('41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d', 'hex'), + hexStringToBytes('41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d'), ], [ Chain.Rinkeby, - Buffer.from('6341fd3daf94b748c72ced5a5b26028f2474f5f00d824504e4fa37a75767e177', 'hex'), + hexStringToBytes('6341fd3daf94b748c72ced5a5b26028f2474f5f00d824504e4fa37a75767e177'), ], [ Chain.Goerli, - Buffer.from('bf7e331f7f7c1dd2e05159666b3bf8bc7a8a3a9eb1d518969eab529dd9b88c1a', 'hex'), + hexStringToBytes('bf7e331f7f7c1dd2e05159666b3bf8bc7a8a3a9eb1d518969eab529dd9b88c1a'), ], [ Chain.Sepolia, - Buffer.from('25a5cc106eea7138acab33231d7160d69cb777ee0c2c553fcddf5138993e6dd9', 'hex'), + hexStringToBytes('25a5cc106eea7138acab33231d7160d69cb777ee0c2c553fcddf5138993e6dd9'), ], ] @@ -323,9 +324,8 @@ tape('[Common]: Hardfork logic', function (t: tape.Test) { msg = 'should provide correct forkHash for HF provided' st.equal(c.forkHash(Hardfork.SpuriousDragon), '0x3edd5b10', msg) - const genesisHash = Buffer.from( - 'd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3', - 'hex' + const genesisHash = hexStringToBytes( + 'd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3' ) st.equal(c.forkHash(Hardfork.SpuriousDragon, genesisHash), '0x3edd5b10', msg) diff --git a/packages/common/test/timestamp.spec.ts b/packages/common/test/timestamp.spec.ts index f92ff3120b..510ddf8472 100644 --- a/packages/common/test/timestamp.spec.ts +++ b/packages/common/test/timestamp.spec.ts @@ -1,3 +1,4 @@ +import { hexStringToBytes } from '@ethereumjs/util' import * as tape from 'tape' import { Chain, Common, Hardfork } from '../src' @@ -97,9 +98,8 @@ tape('[Common]: Timestamp Hardfork logic', function (t: tape.Test) { ]) const c = Common.custom({ hardforks }, { baseChain: Chain.Mainnet }) - const mainnetGenesisHash = Buffer.from( - 'd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3', - 'hex' + const mainnetGenesisHash = hexStringToBytes( + 'd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3' ) for (const hf of c.hardforks()) { if (typeof hf.forkHash === 'string') { @@ -141,9 +141,8 @@ tape('[Common]: Timestamp Hardfork logic', function (t: tape.Test) { ]) const c = Common.custom({ hardforks }, { baseChain: Chain.Mainnet }) - const mainnetGenesisHash = Buffer.from( - 'd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3', - 'hex' + const mainnetGenesisHash = hexStringToBytes( + 'd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3' ) let noForkHashes = c.hardforks().reduce((acc, hf) => { diff --git a/packages/common/test/utils.spec.ts b/packages/common/test/utils.spec.ts index 9e25824397..fd7111c39f 100644 --- a/packages/common/test/utils.spec.ts +++ b/packages/common/test/utils.spec.ts @@ -1,3 +1,4 @@ +import { hexStringToBytes } from '@ethereumjs/util' import * as tape from 'tape' import { Common } from '../src/common' @@ -63,9 +64,8 @@ tape('[Utils/Parse]', (t) => { const json = require(`../../blockchain/test/testdata/geth-genesis-kiln.json`) const common = Common.fromGethGenesis(json, { chain: 'customChain', - genesisHash: Buffer.from( - '51c7fe41be669f69c45c33a56982cbde405313342d9e2b00d7c91a7b284dd4f8', - 'hex' + genesisHash: hexStringToBytes( + '51c7fe41be669f69c45c33a56982cbde405313342d9e2b00d7c91a7b284dd4f8' ), mergeForkIdPostMerge: false, }) diff --git a/packages/devp2p/examples/peer-communication-les.ts b/packages/devp2p/examples/peer-communication-les.ts index 40d0fc884e..f6ee474f97 100644 --- a/packages/devp2p/examples/peer-communication-les.ts +++ b/packages/devp2p/examples/peer-communication-les.ts @@ -1,4 +1,4 @@ -import { randomBytes } from 'crypto' +import { bytesToInt, intToBytes, randomBytes } from '@ethereumjs/util' import { Block, BlockHeader } from '@ethereumjs/block' import { Chain, Common, Hardfork } from '@ethereumjs/common' import { TypedTransaction } from '@ethereumjs/tx' @@ -7,14 +7,12 @@ import ms = require('ms') import * as devp2p from '../src/index' import { LES, Peer } from '../src/index' +import { bytesToHex, hexToBytes } from 'ethereum-cryptography/utils' const PRIVATE_KEY = randomBytes(32) const GENESIS_TD = 1 -const GENESIS_HASH = Buffer.from( - '6341fd3daf94b748c72ced5a5b26028f2474f5f00d824504e4fa37a75767e177', - 'hex' -) +const GENESIS_HASH = hexToBytes('6341fd3daf94b748c72ced5a5b26028f2474f5f00d824504e4fa37a75767e177') const common = new Common({ chain: Chain.Rinkeby, hardfork: Hardfork.London }) const bootstrapNodes = common.bootstrapNodes() @@ -79,19 +77,24 @@ rlpx.on('peer:added', (peer) => { ) les.sendStatus({ - headTd: devp2p.int2buffer(GENESIS_TD), + headTd: intToBytes(GENESIS_TD), headHash: GENESIS_HASH, - headNum: Buffer.from([]), + headNum: Uint8Array.from([]), genesisHash: GENESIS_HASH, - announceType: devp2p.int2buffer(0), - recentTxLookup: devp2p.int2buffer(1), - forkID: [Buffer.from('3b8e0691', 'hex'), devp2p.int2buffer(1)], + announceType: intToBytes(0), + recentTxLookup: intToBytes(1), + forkID: [hexToBytes('3b8e0691'), intToBytes(1)], }) les.once('status', (status: LES.Status) => { const msg = [ - Buffer.from([]), - [devp2p.buffer2int(status['headNum']), Buffer.from([1]), Buffer.from([]), Buffer.from([1])], + Uint8Array.from([]), + [ + bytesToInt(status['headNum']), + Uint8Array.from([1]), + Uint8Array.from([]), + Uint8Array.from([1]), + ], ] les.sendMessage(devp2p.LES.MESSAGE_CODES.GET_BLOCK_HEADERS, msg) }) @@ -109,7 +112,7 @@ rlpx.on('peer:added', (peer) => { setTimeout(() => { les.sendMessage(devp2p.LES.MESSAGE_CODES.GET_BLOCK_BODIES, [ - Buffer.from([1]), + Uint8Array.from([1]), [header.hash()], ]) requests.bodies.push(header) @@ -196,7 +199,7 @@ dpt.addPeer({ address: '127.0.0.1', udpPort: 30303, tcpPort: 30303 }) .catch((err) => console.log(`error on connection to local node: ${err.stack ?? err}`)) */ function onNewBlock(block: Block, peer: Peer) { - const blockHashHex = block.hash().toString('hex') + const blockHashHex = bytesToHex(block.hash()) const blockNumber = block.header.number console.log( diff --git a/packages/devp2p/examples/peer-communication.ts b/packages/devp2p/examples/peer-communication.ts index 64a79a1077..f71f3ce0c2 100644 --- a/packages/devp2p/examples/peer-communication.ts +++ b/packages/devp2p/examples/peer-communication.ts @@ -1,15 +1,15 @@ -import { randomBytes } from 'crypto' +import { bytesToInt, intToBytes, randomBytes } from '@ethereumjs/util' import { Block, BlockHeader } from '@ethereumjs/block' import { Chain, Common, Hardfork } from '@ethereumjs/common' import { RLP } from '@ethereumjs/rlp' import { TransactionFactory, TypedTransaction } from '@ethereumjs/tx' -import { arrToBufArr } from '@ethereumjs/util' import chalk from 'chalk' import * as LRUCache from 'lru-cache' import ms = require('ms') import * as devp2p from '../src/index' import { ETH, Peer } from '../src/index' +import { bytesToHex, equalsBytes, hexToBytes } from 'ethereum-cryptography/utils' const PRIVATE_KEY = randomBytes(32) @@ -37,10 +37,8 @@ const REMOTE_CLIENTID_FILTER = [ const CHECK_BLOCK_TITLE = 'Berlin Fork' // Only for debugging/console output const CHECK_BLOCK_NR = 12244000 const CHECK_BLOCK = '1638380ab737e0e916bd1c7f23bd2bab2a532e44b90047f045f262ee21c42b21' -const CHECK_BLOCK_HEADER = arrToBufArr( - RLP.decode( - '0xf90219a0d44a4d33e28d7ea9edd12b69bd32b394587eee498b0e2543ce2bad1877ffbeaca01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347941ad91ee08f21be3de0ba2ba6918e714da6b45836a0fdec060ee45e55da9e36060fc95dddd0bdc47e447224666a895d9f0dc9adaa0ca0092d9fcc02ca9b372daec726704ce720d3aa366739868f4820ecaabadb9ac309a0974fee017515a46303f467b6fd50872994db1b0ea64d3455bad93ff9678aced9b90100356050004c5c89691add79838a01d4c302419252a4d3c96e9273908b7ee84660886c070607b4928c416a1800746a0d1dbb442d0baf06eea321422263726748600cc200e82aec08336863514d12d665718016989189c116bc0947046cc6718110586c11464a189000a11a41cc96991970153d88840768170244197e164c6204249b9091a0052ac85088c8108a4418dd2903690a036722623888ea14e90458a390a305a2342cb02766094f68c4100036330719848b48411614686717ab6068a46318204232429dc42020608802ceecd66c3c33a3a1fc6e82522049470328a4a81ba07c6604228ba94f008476005087a6804463696b41002650c0fdf548448a90408717ca31b6d618e883bad42083be153b83bdfbb1846078104798307834383639373636353666366532303530366636663663a0ae1de0acd35a98e211c7e276ad7524bb84a5e1b8d33dd7d1c052b095b564e8b888cca66773148b6e12' - ) +const CHECK_BLOCK_HEADER = RLP.decode( + '0xf90219a0d44a4d33e28d7ea9edd12b69bd32b394587eee498b0e2543ce2bad1877ffbeaca01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347941ad91ee08f21be3de0ba2ba6918e714da6b45836a0fdec060ee45e55da9e36060fc95dddd0bdc47e447224666a895d9f0dc9adaa0ca0092d9fcc02ca9b372daec726704ce720d3aa366739868f4820ecaabadb9ac309a0974fee017515a46303f467b6fd50872994db1b0ea64d3455bad93ff9678aced9b90100356050004c5c89691add79838a01d4c302419252a4d3c96e9273908b7ee84660886c070607b4928c416a1800746a0d1dbb442d0baf06eea321422263726748600cc200e82aec08336863514d12d665718016989189c116bc0947046cc6718110586c11464a189000a11a41cc96991970153d88840768170244197e164c6204249b9091a0052ac85088c8108a4418dd2903690a036722623888ea14e90458a390a305a2342cb02766094f68c4100036330719848b48411614686717ab6068a46318204232429dc42020608802ceecd66c3c33a3a1fc6e82522049470328a4a81ba07c6604228ba94f008476005087a6804463696b41002650c0fdf548448a90408717ca31b6d618e883bad42083be153b83bdfbb1846078104798307834383639373636353666366532303530366636663663a0ae1de0acd35a98e211c7e276ad7524bb84a5e1b8d33dd7d1c052b095b564e8b888cca66773148b6e12' ) const getPeerAddr = (peer: Peer) => `${peer._socket.remoteAddress}:${peer._socket.remotePort}` @@ -88,15 +86,9 @@ rlpx.on('peer:added', (peer) => { ) eth.sendStatus({ - td: devp2p.int2buffer(17179869184), // total difficulty in genesis block - bestHash: Buffer.from( - 'd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3', - 'hex' - ), - genesisHash: Buffer.from( - 'd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3', - 'hex' - ), + td: intToBytes(17179869184), // total difficulty in genesis block + bestHash: hexToBytes('d4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3'), + genesisHash: hexToBytes('d4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3'), }) // check CHECK_BLOCK @@ -104,8 +96,8 @@ rlpx.on('peer:added', (peer) => { let forkVerified = false eth.once('status', () => { eth.sendMessage(devp2p.ETH.MESSAGE_CODES.GET_BLOCK_HEADERS, [ - Buffer.from([1]), - [devp2p.int2buffer(CHECK_BLOCK_NR), Buffer.from([1]), Buffer.from([]), Buffer.from([])], + Uint8Array.from([1]), + [intToBytes(CHECK_BLOCK_NR), Uint8Array.from([1]), Uint8Array.from([]), Uint8Array.from([])], ]) forkDrop = setTimeout(() => { peer.disconnect(devp2p.DISCONNECT_REASONS.USELESS_PEER) @@ -126,11 +118,11 @@ rlpx.on('peer:added', (peer) => { for (const item of payload) { const blockHash = item[0] - if (blocksCache.has(blockHash.toString('hex'))) continue + if (blocksCache.has(bytesToHex(blockHash))) continue setTimeout(() => { eth.sendMessage(devp2p.ETH.MESSAGE_CODES.GET_BLOCK_HEADERS, [ - Buffer.from([2]), - [blockHash, Buffer.from([1]), Buffer.from([]), Buffer.from([])], + Uint8Array.from([2]), + [blockHash, Uint8Array.from([1]), Uint8Array.from([]), Uint8Array.from([])], ]) requests.headers.push(blockHash) }, ms('0.1s')) @@ -150,7 +142,7 @@ rlpx.on('peer:added', (peer) => { case devp2p.ETH.MESSAGE_CODES.GET_BLOCK_HEADERS: { const headers = [] // hack - if (devp2p.buffer2int(payload[1][0]) === CHECK_BLOCK_NR) { + if (bytesToInt(payload[1][0]) === CHECK_BLOCK_NR) { headers.push(CHECK_BLOCK_HEADER) } @@ -174,7 +166,7 @@ rlpx.on('peer:added', (peer) => { const expectedHash = CHECK_BLOCK const header = BlockHeader.fromValuesArray(payload[1][0], { common }) - if (header.hash().toString('hex') === expectedHash) { + if (bytesToHex(header.hash()) === expectedHash) { console.log(`${addr} verified to be on the same side of the ${CHECK_BLOCK_TITLE}`) clearTimeout(forkDrop) forkVerified = true @@ -191,11 +183,11 @@ rlpx.on('peer:added', (peer) => { const header = BlockHeader.fromValuesArray(payload[1][0], { common }) while (requests.headers.length > 0) { const blockHash = requests.headers.shift() - if (header.hash().equals(blockHash)) { + if (equalsBytes(header.hash(), blockHash)) { isValidPayload = true setTimeout(() => { eth.sendMessage(devp2p.ETH.MESSAGE_CODES.GET_BLOCK_BODIES, [ - Buffer.from([3]), + Uint8Array.from([3]), [blockHash], ]) requests.bodies.push(header) @@ -205,7 +197,7 @@ rlpx.on('peer:added', (peer) => { } if (!isValidPayload) { - console.log(`${addr} received wrong block header ${header.hash().toString('hex')}`) + console.log(`${addr} received wrong block header ${bytesToHex(header.hash())}`) } } @@ -338,7 +330,7 @@ dpt.addPeer({ address: '127.0.0.1', udpPort: 30303, tcpPort: 30303 }) const txCache = new LRUCache({ max: 1000 }) function onNewTx(tx: TypedTransaction, peer: Peer) { - const txHashHex = tx.hash().toString('hex') + const txHashHex = bytesToHex(tx.hash()) if (txCache.has(txHashHex)) return txCache.set(txHashHex, true) @@ -347,7 +339,7 @@ function onNewTx(tx: TypedTransaction, peer: Peer) { const blocksCache = new LRUCache({ max: 100 }) function onNewBlock(block: Block, peer: Peer) { - const blockHashHex = block.hash().toString('hex') + const blockHashHex = bytesToHex(block.hash()) const blockNumber = block.header.number if (blocksCache.has(blockHashHex)) return diff --git a/packages/devp2p/examples/simple.ts b/packages/devp2p/examples/simple.ts index 6105551209..8cf80e3c1c 100644 --- a/packages/devp2p/examples/simple.ts +++ b/packages/devp2p/examples/simple.ts @@ -1,5 +1,6 @@ import { Chain, Common } from '@ethereumjs/common' import chalk from 'chalk' +import { hexToBytes } from 'ethereum-cryptography/utils' import { DPT } from '../src/index' @@ -15,7 +16,7 @@ const BOOTNODES = bootstrapNodes.map((node: any) => { } }) -const dpt = new DPT(Buffer.from(PRIVATE_KEY, 'hex'), { +const dpt = new DPT(hexToBytes(PRIVATE_KEY), { endpoint: { address: '0.0.0.0', udpPort: null, @@ -27,14 +28,12 @@ const dpt = new DPT(Buffer.from(PRIVATE_KEY, 'hex'), { dpt.on('error', (err) => console.error(chalk.red(err.stack ?? err))) dpt.on('peer:added', (peer) => { - const info = `(${peer.id.toString('hex')},${peer.address},${peer.udpPort},${peer.tcpPort})` + const info = `(${bytesToHex(peer.id)},${peer.address},${peer.udpPort},${peer.tcpPort})` console.log(chalk.green(`New peer: ${info} (total: ${dpt.getPeers().length})`)) }) dpt.on('peer:removed', (peer) => { - console.log( - chalk.yellow(`Remove peer: ${peer.id.toString('hex')} (total: ${dpt.getPeers().length})`) - ) + console.log(chalk.yellow(`Remove peer: ${bytesToHex(peer.id)} (total: ${dpt.getPeers().length})`)) }) // for accept incoming connections uncomment next line diff --git a/packages/devp2p/package.json b/packages/devp2p/package.json index 722b94192f..72befc7883 100644 --- a/packages/devp2p/package.json +++ b/packages/devp2p/package.json @@ -53,13 +53,10 @@ "@ethereumjs/rlp": "^4.0.1", "@ethereumjs/util": "^8.0.5", "@scure/base": "1.1.1", - "@types/bl": "^2.1.0", "@types/k-bucket": "^5.0.0", "@types/lru-cache": "^5.1.0", - "bl": "^1.1.2", "debug": "^4.3.3", "ethereum-cryptography": "^1.1.2", - "ip": "^1.1.3", "k-bucket": "^5.0.0", "lru-cache": "^5.1.1", "ms": "^0.7.1", diff --git a/packages/devp2p/scripts/singlePeerRun.ts b/packages/devp2p/scripts/singlePeerRun.ts index c2de2eaa6e..18fdd64f82 100644 --- a/packages/devp2p/scripts/singlePeerRun.ts +++ b/packages/devp2p/scripts/singlePeerRun.ts @@ -1,4 +1,4 @@ -import { randomBytes } from 'crypto' +import { randomBytes } from '@ethereumjs/util' import { Chain, Common } from '@ethereumjs/common' import * as devp2p from '../src/index' diff --git a/packages/devp2p/src/@types/snappyjs/index.d.ts b/packages/devp2p/src/@types/snappyjs/index.d.ts index 2a77dae624..2968938de8 100644 --- a/packages/devp2p/src/@types/snappyjs/index.d.ts +++ b/packages/devp2p/src/@types/snappyjs/index.d.ts @@ -1,4 +1,4 @@ declare module 'snappyjs' { - function uncompress(data: Buffer): Buffer - function compress(data: Buffer): Buffer + function uncompress(data: Uint8Array): Uint8Array + function compress(data: Uint8Array): Uint8Array } diff --git a/packages/devp2p/src/dns/enr.ts b/packages/devp2p/src/dns/enr.ts index d5813edb62..e741de4038 100644 --- a/packages/devp2p/src/dns/enr.ts +++ b/packages/devp2p/src/dns/enr.ts @@ -1,7 +1,7 @@ import { RLP } from '@ethereumjs/rlp' -import { arrToBufArr, bufArrToArr } from '@ethereumjs/util' import { base32, base64url } from '@scure/base' import { ecdsaVerify } from 'ethereum-cryptography/secp256k1-compat' +import { bytesToUtf8, utf8ToBytes } from 'ethereum-cryptography/utils' import { Multiaddr } from 'multiaddr' import { sscanf } from 'scanf' @@ -60,21 +60,21 @@ export class ENR { while (enrMod.length % 4 !== 0) { enrMod = enrMod + '=' } - const base64BufferEnr = Buffer.from(base64url.decode(enrMod)) - const decoded = arrToBufArr(RLP.decode(Uint8Array.from(base64BufferEnr))) as Buffer[] + const base64BytesEnr = base64url.decode(enrMod) + const decoded = RLP.decode(base64BytesEnr) const [signature, seq, ...kvs] = decoded // Convert ENR key/value pairs to object - const obj: Record = {} + const obj: Record = {} for (let i = 0; i < kvs.length; i += 2) { - obj[kvs[i].toString()] = Buffer.from(kvs[i + 1]) + obj[bytesToUtf8(kvs[i] as Uint8Array)] = kvs[i + 1] as Uint8Array } // Validate sig const isVerified = ecdsaVerify( - signature, - keccak256(Buffer.from(RLP.encode(bufArrToArr([seq, ...kvs])))), + signature as Uint8Array, + keccak256(RLP.encode([seq, ...kvs])), obj.secp256k1 ) @@ -123,14 +123,14 @@ export class ENR { // of the record content, excluding the `sig=` part, encoded as URL-safe base64 string // (Trailing recovery bit must be trimmed to pass `ecdsaVerify` method) const signedComponent = root.split(' sig')[0] - const signedComponentBuffer = Buffer.from(signedComponent) - const signatureBuffer = Buffer.from( + const signedComponentBytes = utf8ToBytes(signedComponent) + const signatureBytes = Uint8Array.from( [...base64url.decode(rootVals.signature + '=').values()].slice(0, 64) ) - const keyBuffer = Buffer.from(decodedPublicKey) + const keyBytes = Uint8Array.from(decodedPublicKey) - const isVerified = ecdsaVerify(signatureBuffer, keccak256(signedComponentBuffer), keyBuffer) + const isVerified = ecdsaVerify(signatureBytes, keccak256(signedComponentBytes), keyBytes) if (!isVerified) throw new Error('Unable to verify ENR root signature') @@ -177,13 +177,13 @@ export class ENR { /** * Gets relevant multiaddr conversion codes for ipv4, ipv6 and tcp, udp formats - * @param {Buffer} protocolId + * @param {Uint8Array} protocolId * @return {ProtocolCodes} */ - static _getIpProtocolConversionCodes(protocolId: Buffer): ProtocolCodes { + static _getIpProtocolConversionCodes(protocolId: Uint8Array): ProtocolCodes { let ipCode - switch (protocolId.toString()) { + switch (bytesToUtf8(protocolId)) { case 'v4': ipCode = Multiaddr.protocols.names.ip4.code break diff --git a/packages/devp2p/src/dpt/ban-list.ts b/packages/devp2p/src/dpt/ban-list.ts index 25243ecac7..fe130f50d8 100644 --- a/packages/devp2p/src/dpt/ban-list.ts +++ b/packages/devp2p/src/dpt/ban-list.ts @@ -16,14 +16,14 @@ export class BanList { this.lru = new LRUCache({ max: 30000 }) // 10k should be enough (each peer obj can has 3 keys) } - add(obj: string | Buffer | PeerInfo, maxAge?: number) { + add(obj: string | Uint8Array | PeerInfo, maxAge?: number) { for (const key of KBucket.getKeys(obj)) { this.lru.set(key, true, maxAge) debug(`Added peer ${formatLogId(key, verbose)}, size: ${this.lru.length}`) } } - has(obj: string | Buffer | PeerInfo): boolean { + has(obj: string | Uint8Array | PeerInfo): boolean { return KBucket.getKeys(obj).some((key: string) => Boolean(this.lru.get(key))) } } diff --git a/packages/devp2p/src/dpt/dpt.ts b/packages/devp2p/src/dpt/dpt.ts index 90840f83a3..224730c6ff 100644 --- a/packages/devp2p/src/dpt/dpt.ts +++ b/packages/devp2p/src/dpt/dpt.ts @@ -1,10 +1,10 @@ -import { randomBytes } from 'crypto' +import { bytesToInt, randomBytes } from '@ethereumjs/util' import { getPublicKey } from 'ethereum-cryptography/secp256k1' import { EventEmitter } from 'events' import ms = require('ms') import { DNS } from '../dns' -import { buffer2int, devp2pDebug, pk2id } from '../util' +import { devp2pDebug, pk2id } from '../util' import { BanList } from './ban-list' import { KBucket } from './kbucket' @@ -15,7 +15,7 @@ import type { Debugger } from 'debug' const DEBUG_BASE_NAME = 'dpt' export interface PeerInfo { - id?: Uint8Array | Buffer + id?: Uint8Array address?: string udpPort?: number | null tcpPort?: number | null @@ -87,12 +87,12 @@ export interface DPTOptions { } export class DPT extends EventEmitter { - privateKey: Buffer + privateKey: Uint8Array banlist: BanList dns: DNS _debug: Debugger - private _id: Buffer | undefined + private _id: Uint8Array | undefined private _kbucket: KBucket private _server: DPTServer private _refreshIntervalId: NodeJS.Timeout @@ -103,11 +103,11 @@ export class DPT extends EventEmitter { private _dnsNetworks: string[] private _dnsAddr: string - constructor(privateKey: Buffer, options: DPTOptions) { + constructor(privateKey: Uint8Array, options: DPTOptions) { super() - this.privateKey = Buffer.from(privateKey) - this._id = pk2id(Buffer.from(getPublicKey(this.privateKey, false))) + this.privateKey = privateKey + this._id = pk2id(getPublicKey(this.privateKey, false)) this._shouldFindNeighbours = options.shouldFindNeighbours ?? true this._shouldGetDnsPeers = options.shouldGetDnsPeers ?? false // By default, tries to connect to 12 new peers every 3s @@ -220,7 +220,7 @@ export class DPT extends EventEmitter { } } - getPeer(obj: string | Buffer | PeerInfo) { + getPeer(obj: string | Uint8Array | PeerInfo) { return this._kbucket.get(obj) } @@ -228,7 +228,7 @@ export class DPT extends EventEmitter { return this._kbucket.getAll() } - getClosestPeers(id: string) { + getClosestPeers(id: Uint8Array) { return this._kbucket.closest(id) } @@ -236,7 +236,7 @@ export class DPT extends EventEmitter { this._kbucket.remove(obj) } - banPeer(obj: string | Buffer | PeerInfo, maxAge?: number) { + banPeer(obj: string | Uint8Array | PeerInfo, maxAge?: number) { this.banlist.add(obj, maxAge) this._kbucket.remove(obj) } @@ -258,7 +258,7 @@ export class DPT extends EventEmitter { for (const peer of peers) { // Randomly distributed selector based on peer ID // to decide on subdivided execution - const selector = buffer2int((peer.id as Buffer).slice(0, 1)) % 10 + const selector = bytesToInt((peer.id as Uint8Array).subarray(0, 1)) % 10 if (selector === this._refreshIntervalSelectionCounter) { this._server.findneighbours(peer, randomBytes(64)) } diff --git a/packages/devp2p/src/dpt/kbucket.ts b/packages/devp2p/src/dpt/kbucket.ts index c9a99e262e..ece927dc61 100644 --- a/packages/devp2p/src/dpt/kbucket.ts +++ b/packages/devp2p/src/dpt/kbucket.ts @@ -1,3 +1,4 @@ +import { bytesToHex } from 'ethereum-cryptography/utils' import { EventEmitter } from 'events' import _KBucket = require('k-bucket') @@ -7,14 +8,14 @@ const KBUCKET_SIZE = 16 const KBUCKET_CONCURRENCY = 3 export interface CustomContact extends PeerInfo { - id: Uint8Array | Buffer + id: Uint8Array vectorClock: number } export class KBucket extends EventEmitter { _peers: Map = new Map() _kbucket: _KBucket - constructor(localNodeId: Buffer) { + constructor(localNodeId: Uint8Array) { super() this._kbucket = new _KBucket({ @@ -42,12 +43,12 @@ export class KBucket extends EventEmitter { }) } - static getKeys(obj: Buffer | string | PeerInfo): string[] { - if (Buffer.isBuffer(obj)) return [obj.toString('hex')] + static getKeys(obj: Uint8Array | string | PeerInfo): string[] { + if (obj instanceof Uint8Array) return [bytesToHex(obj)] if (typeof obj === 'string') return [obj] const keys = [] - if (Buffer.isBuffer(obj.id)) keys.push(obj.id.toString('hex')) + if (obj.id instanceof Uint8Array) keys.push(bytesToHex(obj.id)) if (obj.address !== undefined && typeof obj.tcpPort === 'number') keys.push(`${obj.address}:${obj.tcpPort}`) return keys @@ -58,7 +59,7 @@ export class KBucket extends EventEmitter { if (!isExists) this._kbucket.add(peer as CustomContact) } - get(obj: Buffer | string | PeerInfo) { + get(obj: Uint8Array | string | PeerInfo) { for (const key of KBucket.getKeys(obj)) { const peer = this._peers.get(key) if (peer !== undefined) return peer @@ -71,11 +72,11 @@ export class KBucket extends EventEmitter { return this._kbucket.toArray() } - closest(id: string): PeerInfo[] { - return this._kbucket.closest(Buffer.from(id), KBUCKET_SIZE) + closest(id: Uint8Array): PeerInfo[] { + return this._kbucket.closest(id, KBUCKET_SIZE) } - remove(obj: Buffer | string | PeerInfo) { + remove(obj: Uint8Array | string | PeerInfo) { const peer = this.get(obj) if (peer !== null) this._kbucket.remove((peer as CustomContact).id) } diff --git a/packages/devp2p/src/dpt/message.ts b/packages/devp2p/src/dpt/message.ts index 01326b8fbc..995d7e08c6 100644 --- a/packages/devp2p/src/dpt/message.ts +++ b/packages/devp2p/src/dpt/message.ts @@ -1,10 +1,18 @@ import { RLP } from '@ethereumjs/rlp' -import { bufArrToArr } from '@ethereumjs/util' +import { bytesToInt, intToBytes } from '@ethereumjs/util' import { debug as createDebugLogger } from 'debug' import { ecdsaRecover, ecdsaSign } from 'ethereum-cryptography/secp256k1-compat' -import * as ip from 'ip' - -import { assertEq, buffer2int, int2buffer, keccak256, unstrictDecode } from '../util' +import { bytesToHex, bytesToUtf8, concatBytes } from 'ethereum-cryptography/utils' + +import { + assertEq, + ipToBytes, + ipToString, + isV4Format, + isV6Format, + keccak256, + unstrictDecode, +} from '../util' import type { PeerInfo } from './dpt' @@ -16,57 +24,55 @@ function getTimestamp() { const timestamp = { encode(value = getTimestamp() + 60) { - const buffer = Buffer.allocUnsafe(4) - buffer.writeUInt32BE(value, 0) - return buffer + const bytes = new Uint8Array(4) + new DataView(bytes.buffer).setUint32(0, value) + return bytes }, - decode(buffer: Buffer) { - if (buffer.length !== 4) - throw new RangeError(`Invalid timestamp buffer :${buffer.toString('hex')}`) - return buffer.readUInt32BE(0) + decode(bytes: Uint8Array) { + if (bytes.length !== 4) throw new RangeError(`Invalid timestamp bytes :${bytesToHex(bytes)}`) + return new DataView(bytes.buffer).getUint32(0) }, } const address = { encode(value: string) { - if (ip.isV4Format(value)) return ip.toBuffer(value) - if (ip.isV6Format(value)) return ip.toBuffer(value) + if (isV4Format(value)) return ipToBytes(value) + if (isV6Format(value)) return ipToBytes(value) throw new Error(`Invalid address: ${value}`) }, - decode(buffer: Buffer) { - if (buffer.length === 4) return ip.toString(buffer) - if (buffer.length === 16) return ip.toString(buffer) + decode(bytes: Uint8Array) { + if (bytes.length === 4) return ipToString(bytes) + if (bytes.length === 16) return ipToString(bytes) - const str = buffer.toString() - if (ip.isV4Format(str) || ip.isV6Format(str)) return str + const str = bytesToUtf8(bytes) + if (isV4Format(str) || isV6Format(str)) return str // also can be host, but skip it right now (because need async function for resolve) - throw new Error(`Invalid address buffer: ${buffer.toString('hex')}`) + throw new Error(`Invalid address bytes: ${bytesToHex(bytes)}`) }, } const port = { - encode(value: number | null): Buffer { - if (value === null) return Buffer.allocUnsafe(0) + encode(value: number | null): Uint8Array { + if (value === null) return new Uint8Array() if (value >>> 16 > 0) throw new RangeError(`Invalid port: ${value}`) - return Buffer.from([(value >>> 8) & 0xff, (value >>> 0) & 0xff]) + return Uint8Array.from([(value >>> 8) & 0xff, (value >>> 0) & 0xff]) }, - decode(buffer: Buffer): number | null { - if (buffer.length === 0) return null - // if (buffer.length !== 2) throw new RangeError(`Invalid port buffer: ${buffer.toString('hex')}`) - return buffer2int(buffer) + decode(bytes: Uint8Array): number | null { + if (bytes.length === 0) return null + return bytesToInt(bytes) }, } const endpoint = { - encode(obj: PeerInfo): Buffer[] { + encode(obj: PeerInfo): Uint8Array[] { return [ address.encode(obj.address!), port.encode(obj.udpPort ?? null), port.encode(obj.tcpPort ?? null), ] }, - decode(payload: Buffer[]): PeerInfo { + decode(payload: Uint8Array[]): PeerInfo { return { address: address.decode(payload[0]), udpPort: port.decode(payload[1]), @@ -75,12 +81,12 @@ const endpoint = { }, } -type InPing = { [0]: Buffer; [1]: Buffer[]; [2]: Buffer[]; [3]: Buffer } +type InPing = { [0]: Uint8Array; [1]: Uint8Array[]; [2]: Uint8Array[]; [3]: Uint8Array } type OutPing = { version: number; from: PeerInfo; to: PeerInfo; timestamp: number } const ping = { encode(obj: OutPing): InPing { return [ - int2buffer(obj.version), + intToBytes(obj.version), endpoint.encode(obj.from), endpoint.encode(obj.to), timestamp.encode(obj.timestamp), @@ -88,7 +94,7 @@ const ping = { }, decode(payload: InPing): OutPing { return { - version: buffer2int(payload[0]), + version: bytesToInt(payload[0]), from: endpoint.decode(payload[1]), to: endpoint.decode(payload[2]), timestamp: timestamp.decode(payload[3]), @@ -96,8 +102,8 @@ const ping = { }, } -type OutPong = { to: PeerInfo; hash: Buffer; timestamp: number } -type InPong = { [0]: Buffer[]; [1]: Buffer[]; [2]: Buffer } +type OutPong = { to: PeerInfo; hash: Uint8Array; timestamp: number } +type InPong = { [0]: Uint8Array[]; [1]: Uint8Array[]; [2]: Uint8Array } const pong = { encode(obj: OutPong) { return [endpoint.encode(obj.to), obj.hash, timestamp.encode(obj.timestamp)] @@ -112,7 +118,7 @@ const pong = { } type OutFindMsg = { id: string; timestamp: number } -type InFindMsg = { [0]: string; [1]: Buffer } +type InFindMsg = { [0]: string; [1]: Uint8Array } const findneighbours = { encode(obj: OutFindMsg): InFindMsg { return [obj.id, timestamp.encode(obj.timestamp)] @@ -126,11 +132,11 @@ const findneighbours = { } type InNeighborMsg = { peers: PeerInfo[]; timestamp: number } -type OutNeighborMsg = { [0]: Buffer[][]; [1]: Buffer } +type OutNeighborMsg = { [0]: Uint8Array[][]; [1]: Uint8Array } const neighbours = { encode(obj: InNeighborMsg): OutNeighborMsg { return [ - obj.peers.map((peer: PeerInfo) => endpoint.encode(peer).concat(peer.id! as Buffer)), + obj.peers.map((peer: PeerInfo) => endpoint.encode(peer).concat(peer.id! as Uint8Array)), timestamp.encode(obj.timestamp), ] }, @@ -168,36 +174,32 @@ const types: Types = { // 97 type // [98, length) data -export function encode(typename: string, data: T, privateKey: Buffer) { +export function encode(typename: string, data: T, privateKey: Uint8Array) { const type: number = types.byName[typename] as number if (type === undefined) throw new Error(`Invalid typename: ${typename}`) const encodedMsg = messages[typename].encode(data) - const typedata = Buffer.concat([ - Buffer.from([type]), - Buffer.from(RLP.encode(bufArrToArr(encodedMsg))), - ]) + const typedata = concatBytes(Uint8Array.from([type]), RLP.encode(encodedMsg)) const sighash = keccak256(typedata) const sig = ecdsaSign(sighash, privateKey) - const hashdata = Buffer.concat([Buffer.from(sig.signature), Buffer.from([sig.recid]), typedata]) + const hashdata = concatBytes(sig.signature, Uint8Array.from([sig.recid]), typedata) const hash = keccak256(hashdata) - return Buffer.concat([hash, hashdata]) + return concatBytes(hash, hashdata) } -export function decode(buffer: Buffer) { - const hash = keccak256(buffer.slice(32)) - assertEq(buffer.slice(0, 32), hash, 'Hash verification failed', debug) +export function decode(bytes: Uint8Array) { + const hash = keccak256(bytes.subarray(32)) + assertEq(bytes.subarray(0, 32), hash, 'Hash verification failed', debug) - const typedata = buffer.slice(97) + const typedata = bytes.subarray(97) const type = typedata[0] const typename = types.byType[type] if (typename === undefined) throw new Error(`Invalid type: ${type}`) - const data = messages[typename].decode(unstrictDecode(typedata.slice(1))) + const data = messages[typename].decode(unstrictDecode(typedata.subarray(1))) const sighash = keccak256(typedata) - const signature = buffer.slice(32, 96) - const recoverId = buffer[96] - const publicKey = Buffer.from(ecdsaRecover(signature, recoverId, sighash, false)) - + const signature = bytes.subarray(32, 96) + const recoverId = bytes[96] + const publicKey = ecdsaRecover(signature, recoverId, sighash, false) return { typename, data, publicKey } } diff --git a/packages/devp2p/src/dpt/server.ts b/packages/devp2p/src/dpt/server.ts index 1fd4abf41f..8c70048fa2 100644 --- a/packages/devp2p/src/dpt/server.ts +++ b/packages/devp2p/src/dpt/server.ts @@ -1,5 +1,6 @@ import { debug as createDebugLogger } from 'debug' import * as dgram from 'dgram' +import { bytesToHex } from 'ethereum-cryptography/utils' import { EventEmitter } from 'events' import LRUCache = require('lru-cache') import ms = require('ms') @@ -42,7 +43,7 @@ export interface DPTServerOptions { export class Server extends EventEmitter { _dpt: DPT - _privateKey: Buffer + _privateKey: Uint8Array _timeout: number _endpoint: PeerInfo _requests: Map @@ -50,7 +51,7 @@ export class Server extends EventEmitter { _socket: DgramSocket | null _debug: Debugger - constructor(dpt: DPT, privateKey: Buffer, options: DPTServerOptions) { + constructor(dpt: DPT, privateKey: Uint8Array, options: DPTServerOptions) { super() this._dpt = dpt @@ -68,7 +69,7 @@ export class Server extends EventEmitter { this._socket.once('listening', () => this.emit('listening')) this._socket.once('close', () => this.emit('close')) this._socket.on('error', (err) => this.emit('error', err)) - this._socket.on('message', (msg: Buffer, rinfo: RemoteInfo) => { + this._socket.on('message', (msg: Uint8Array, rinfo: RemoteInfo) => { try { this._handler(msg, rinfo) } catch (err: any) { @@ -109,7 +110,7 @@ export class Server extends EventEmitter { }) const deferred = createDeferred() - const rkey = hash.toString('hex') + const rkey = bytesToHex(hash) this._requests.set(rkey, { peer, deferred, @@ -117,7 +118,7 @@ export class Server extends EventEmitter { if (this._requests.get(rkey) !== undefined) { this._debug( `ping timeout: ${peer.address}:${peer.udpPort} ${ - peer.id ? formatLogId(peer.id.toString('hex'), verbose) : '-' + peer.id ? formatLogId(bytesToHex(peer.id), verbose) : '-' }` ) this._requests.delete(rkey) @@ -131,7 +132,7 @@ export class Server extends EventEmitter { return deferred.promise } - findneighbours(peer: PeerInfo, id: Buffer) { + findneighbours(peer: PeerInfo, id: Uint8Array) { this._isAliveCheck() this._send(peer, 'findneighbours', { id }) } @@ -142,7 +143,7 @@ export class Server extends EventEmitter { _send(peer: PeerInfo, typename: string, data: any) { const debugMsg = `send ${typename} to ${peer.address}:${peer.udpPort} (peerId: ${ - peer.id ? formatLogId(peer.id.toString('hex'), verbose) : '-' + peer.id ? formatLogId(bytesToHex(peer.id), verbose) : '-' })` this.debug(typename, debugMsg) @@ -150,15 +151,15 @@ export class Server extends EventEmitter { if (this._socket && typeof peer.udpPort === 'number') this._socket.send(msg, 0, msg.length, peer.udpPort, peer.address) - return msg.slice(0, 32) // message id + return msg.subarray(0, 32) // message id } - _handler(msg: Buffer, rinfo: RemoteInfo) { - const info = decode(msg) + _handler(msg: Uint8Array, rinfo: RemoteInfo) { + const info = decode(msg) // Dgram serializes everything to `Uint8Array` const peerId = pk2id(info.publicKey) const debugMsg = `received ${info.typename} from ${rinfo.address}:${ rinfo.port - } (peerId: ${formatLogId(peerId.toString('hex'), verbose)})` + } (peerId: ${formatLogId(bytesToHex(peerId), verbose)})` this.debug(info.typename.toString(), debugMsg) // add peer if not in our table @@ -180,13 +181,13 @@ export class Server extends EventEmitter { udpPort: rinfo.port, tcpPort: info.data.from.tcpPort, }, - hash: msg.slice(0, 32), + hash: msg.subarray(0, 32), }) break } case 'pong': { - const rkey = info.data.hash.toString('hex') + const rkey = bytesToHex(info.data.hash) const request = this._requests.get(rkey) if (request !== undefined) { this._requests.delete(rkey) diff --git a/packages/devp2p/src/protocol/eth.ts b/packages/devp2p/src/protocol/eth.ts index ecaa5a4908..1b88a27b04 100644 --- a/packages/devp2p/src/protocol/eth.ts +++ b/packages/devp2p/src/protocol/eth.ts @@ -1,14 +1,16 @@ import { RLP } from '@ethereumjs/rlp' import { - arrToBufArr, - bigIntToBuffer, - bufArrToArr, - bufferToBigInt, - bufferToHex, + bigIntToBytes, + bytesToBigInt, + bytesToHex, + bytesToInt, + bytesToPrefixedHexString, + intToBytes, } from '@ethereumjs/util' +import { hexToBytes } from 'ethereum-cryptography/utils' import * as snappy from 'snappyjs' -import { assertEq, buffer2int, formatLogData, formatLogId, int2buffer } from '../util' +import { assertEq, formatLogData, formatLogId } from '../util' import { EthProtocol, Protocol } from './protocol' @@ -52,14 +54,14 @@ export class ETH extends Protocol { static eth66 = { name: 'eth', version: 66, length: 17, constructor: ETH } _handleMessage(code: ETH.MESSAGE_CODES, data: any) { - const payload = arrToBufArr(RLP.decode(bufArrToArr(data))) + const payload = RLP.decode(data) const messageName = this.getMsgPrefix(code) const debugMsg = this.DEBUG ? `Received ${messageName} message from ${this._peer._socket.remoteAddress}:${this._peer._socket.remotePort}` : undefined if (code !== ETH.MESSAGE_CODES.STATUS && this.DEBUG) { - const logData = formatLogData(data.toString('hex'), this._verbose) + const logData = formatLogData(bytesToHex(data), this._verbose) this.debug(messageName, `${debugMsg}: ${logData}`) } switch (code) { @@ -116,11 +118,11 @@ export class ETH extends Protocol { * Eth 64 Fork ID validation (EIP-2124) * @param forkId Remote fork ID */ - _validateForkId(forkId: Buffer[]) { + _validateForkId(forkId: Uint8Array[]) { const c = this._peer._common - const peerForkHash = bufferToHex(forkId[0]) - const peerNextFork = bufferToBigInt(forkId[1]) + const peerForkHash = bytesToPrefixedHexString(forkId[0]) + const peerNextFork = bytesToBigInt(forkId[1]) if (this._forkHash === peerForkHash) { // There is a known next fork @@ -187,9 +189,9 @@ export class ETH extends Protocol { const status: any = { networkId: this._peerStatus[1], - td: Buffer.from(this._peerStatus[2] as Buffer), - bestHash: Buffer.from(this._peerStatus[3] as Buffer), - genesisHash: Buffer.from(this._peerStatus[4] as Buffer), + td: this._peerStatus[2] as Uint8Array, + bestHash: this._peerStatus[3] as Uint8Array, + genesisHash: this._peerStatus[4] as Uint8Array, } if (this._version >= 64) { @@ -200,7 +202,7 @@ export class ETH extends Protocol { this.debug.bind(this), 'STATUS' ) - this._validateForkId(this._peerStatus[5] as Buffer[]) + this._validateForkId(this._peerStatus[5] as Uint8Array[]) status['forkId'] = this._peerStatus[5] } @@ -214,28 +216,28 @@ export class ETH extends Protocol { return this._version } - _forkHashFromForkId(forkId: Buffer): string { - return `0x${forkId.toString('hex')}` + _forkHashFromForkId(forkId: Uint8Array): string { + return bytesToPrefixedHexString(forkId) } - _nextForkFromForkId(forkId: Buffer): number { - return buffer2int(forkId) + _nextForkFromForkId(forkId: Uint8Array): number { + return bytesToInt(forkId) } _getStatusString(status: ETH.StatusMsg) { - let sStr = `[V:${buffer2int(status[0] as Buffer)}, NID:${buffer2int(status[1] as Buffer)}, TD:${ - status[2].length === 0 ? 0 : buffer2int(status[2] as Buffer) - }` - sStr += `, BestH:${formatLogId(status[3].toString('hex'), this._verbose)}, GenH:${formatLogId( - status[4].toString('hex'), + let sStr = `[V:${bytesToInt(status[0] as Uint8Array)}, NID:${bytesToInt( + status[1] as Uint8Array + )}, TD:${status[2].length === 0 ? 0 : bytesToInt(status[2] as Uint8Array)}` + sStr += `, BestH:${formatLogId( + bytesToHex(status[3] as Uint8Array), this._verbose - )}` + )}, GenH:${formatLogId(bytesToHex(status[4] as Uint8Array), this._verbose)}` if (this._version >= 64) { sStr += `, ForkHash: ${ - status[5] !== undefined ? '0x' + (status[5][0] as Buffer).toString('hex') : '-' + status[5] !== undefined ? bytesToPrefixedHexString(status[5][0] as Uint8Array) : '-' }` sStr += `, ForkNext: ${ - (status[5][1] as Buffer).length > 0 ? buffer2int(status[5][1] as Buffer) : '-' + (status[5][1] as Uint8Array).length > 0 ? bytesToInt(status[5][1] as Uint8Array) : '-' }` } sStr += `]` @@ -245,15 +247,15 @@ export class ETH extends Protocol { sendStatus(status: ETH.StatusOpts) { if (this._status !== null) return this._status = [ - int2buffer(this._version), - bigIntToBuffer(this._peer._common.chainId()), + intToBytes(this._version), + bigIntToBytes(this._peer._common.chainId()), status.td, status.bestHash, status.genesisHash, ] if (this._version >= 64) { if (status.latestBlock) { - const latestBlock = bufferToBigInt(status.latestBlock) + const latestBlock = bytesToBigInt(status.latestBlock) if (latestBlock < this._latestBlock) { throw new Error( 'latest block provided is not matching the HF setting of the Common instance (Rlpx)' @@ -261,12 +263,10 @@ export class ETH extends Protocol { } this._latestBlock = latestBlock } - const forkHashB = Buffer.from(this._forkHash.substr(2), 'hex') + const forkHashB = hexToBytes(this._forkHash.substr(2)) const nextForkB = - this._nextForkBlock === BigInt(0) - ? Buffer.from('', 'hex') - : bigIntToBuffer(this._nextForkBlock) + this._nextForkBlock === BigInt(0) ? new Uint8Array() : bigIntToBytes(this._nextForkBlock) this._status.push([forkHashB, nextForkB]) } @@ -280,7 +280,7 @@ export class ETH extends Protocol { ) } - let payload = Buffer.from(RLP.encode(bufArrToArr(this._status))) + let payload = RLP.encode(this._status) // Use snappy compression if peer supports DevP2P >=v5 if (this._peer._hello !== null && this._peer._hello.protocolVersion >= 5) { @@ -292,10 +292,7 @@ export class ETH extends Protocol { } sendMessage(code: ETH.MESSAGE_CODES, payload: any) { - const logData = formatLogData( - Buffer.from(RLP.encode(bufArrToArr(payload))).toString('hex'), - this._verbose - ) + const logData = formatLogData(bytesToHex(RLP.encode(payload)), this._verbose) if (this.DEBUG) { const messageName = this.getMsgPrefix(code) const debugMsg = `Send ${messageName} message to ${this._peer._socket.remoteAddress}:${this._peer._socket.remotePort}: ${logData}` @@ -334,7 +331,7 @@ export class ETH extends Protocol { throw new Error(`Unknown code ${code}`) } - payload = Buffer.from(RLP.encode(bufArrToArr(payload))) + payload = RLP.encode(payload) // Use snappy compression if peer supports DevP2P >=v5 if (this._peer._hello !== null && this._peer._hello.protocolVersion >= 5) { @@ -350,13 +347,13 @@ export class ETH extends Protocol { } export namespace ETH { - export interface StatusMsg extends Array {} + export interface StatusMsg extends Array {} export type StatusOpts = { - td: Buffer - bestHash: Buffer - latestBlock?: Buffer - genesisHash: Buffer + td: Uint8Array + bestHash: Uint8Array + latestBlock?: Uint8Array + genesisHash: Uint8Array } export enum MESSAGE_CODES { diff --git a/packages/devp2p/src/protocol/les.ts b/packages/devp2p/src/protocol/les.ts index cdfe303adb..0247f9bb8b 100644 --- a/packages/devp2p/src/protocol/les.ts +++ b/packages/devp2p/src/protocol/les.ts @@ -1,10 +1,17 @@ import { RLP } from '@ethereumjs/rlp' -import { arrToBufArr, bigIntToBuffer, bufArrToArr } from '@ethereumjs/util' +import { + bigIntToBytes, + bytesToHex, + bytesToInt, + bytesToUtf8, + intToBytes, + utf8ToBytes, +} from '@ethereumjs/util' import ms = require('ms') import * as snappy from 'snappyjs' import { DISCONNECT_REASONS } from '../rlpx/peer' -import { assertEq, buffer2int, formatLogData, int2buffer } from '../util' +import { assertEq, formatLogData } from '../util' import { EthProtocol, Protocol } from './protocol' @@ -30,12 +37,11 @@ export class LES extends Protocol { static les4 = { name: 'les', version: 4, length: 23, constructor: LES } _handleMessage(code: LES.MESSAGE_CODES, data: any) { - const payload = arrToBufArr(RLP.decode(bufArrToArr(data))) + const payload = RLP.decode(data) const messageName = this.getMsgPrefix(code) const debugMsg = `Received ${messageName} message from ${this._peer._socket.remoteAddress}:${this._peer._socket.remotePort}` - if (code !== LES.MESSAGE_CODES.STATUS) { - const logData = formatLogData(data.toString('hex'), this._verbose) + const logData = formatLogData(bytesToHex(data), this._verbose) this.debug(messageName, `${debugMsg}: ${logData}`) } switch (code) { @@ -49,7 +55,7 @@ export class LES extends Protocol { ) const statusArray: any = {} for (const value of payload as any) { - statusArray[value[0].toString()] = value[1] + statusArray[bytesToUtf8(value[0])] = value[1] } this._peerStatus = statusArray const peerStatusMsg = `${this._peerStatus ? this._getStatusString(this._peerStatus) : ''}` @@ -130,27 +136,27 @@ export class LES extends Protocol { } _getStatusString(status: LES.Status) { - let sStr = `[V:${buffer2int(status['protocolVersion'])}, ` - sStr += `NID:${buffer2int(status['networkId'] as Buffer)}, HTD:${buffer2int( + let sStr = `[V:${bytesToInt(status['protocolVersion'])}, ` + sStr += `NID:${bytesToInt(status['networkId'] as Uint8Array)}, HTD:${bytesToInt( status['headTd'] )}, ` - sStr += `HeadH:${status['headHash'].toString('hex')}, HeadN:${buffer2int(status['headNum'])}, ` - sStr += `GenH:${status['genesisHash'].toString('hex')}` + sStr += `HeadH:${bytesToHex(status['headHash'])}, HeadN:${bytesToInt(status['headNum'])}, ` + sStr += `GenH:${bytesToHex(status['genesisHash'])}` if (status['serveHeaders'] !== undefined) sStr += `, serveHeaders active` if (status['serveChainSince'] !== undefined) - sStr += `, ServeCS: ${buffer2int(status['serveChainSince'])}` + sStr += `, ServeCS: ${bytesToInt(status['serveChainSince'])}` if (status['serveStateSince'] !== undefined) - sStr += `, ServeSS: ${buffer2int(status['serveStateSince'])}` + sStr += `, ServeSS: ${bytesToInt(status['serveStateSince'])}` if (status['txRelay'] !== undefined) sStr += `, txRelay active` if (status['flowControl/BL)'] !== undefined) sStr += `, flowControl/BL set` if (status['flowControl/MRR)'] !== undefined) sStr += `, flowControl/MRR set` if (status['flowControl/MRC)'] !== undefined) sStr += `, flowControl/MRC set` if (status['forkID'] !== undefined) - sStr += `, forkID: [crc32: ${status['forkID'][0].toString('hex')}, nextFork: ${buffer2int( + sStr += `, forkID: [crc32: ${bytesToHex(status['forkID'][0])}, nextFork: ${bytesToInt( status['forkID'][1] )}]` if (status['recentTxLookup'] !== undefined) - sStr += `, recentTxLookup: ${buffer2int(status['recentTxLookup'])}` + sStr += `, recentTxLookup: ${bytesToInt(status['recentTxLookup'])}` sStr += `]` return sStr } @@ -159,16 +165,16 @@ export class LES extends Protocol { if (this._status !== null) return if (status.announceType === undefined) { - status['announceType'] = int2buffer(DEFAULT_ANNOUNCE_TYPE) + status['announceType'] = intToBytes(DEFAULT_ANNOUNCE_TYPE) } - status['protocolVersion'] = int2buffer(this._version) - status['networkId'] = bigIntToBuffer(this._peer._common.chainId()) + status['protocolVersion'] = intToBytes(this._version) + status['networkId'] = bigIntToBytes(this._peer._common.chainId()) this._status = status const statusList: any[][] = [] for (const key of Object.keys(status)) { - statusList.push([Buffer.from(key), status[key]]) + statusList.push([utf8ToBytes(key), status[key]]) } this.debug( @@ -178,7 +184,7 @@ export class LES extends Protocol { } (les${this._version}): ${this._getStatusString(this._status)}` ) - let payload = Buffer.from(RLP.encode(bufArrToArr(statusList))) + let payload = RLP.encode(statusList) // Use snappy compression if peer supports DevP2P >=v5 if (this._peer._hello !== null && this._peer._hello.protocolVersion >= 5) { @@ -196,10 +202,7 @@ export class LES extends Protocol { */ sendMessage(code: LES.MESSAGE_CODES, payload: any) { const messageName = this.getMsgPrefix(code) - const logData = formatLogData( - Buffer.from(RLP.encode(bufArrToArr(payload))).toString('hex'), - this._verbose - ) + const logData = formatLogData(bytesToHex(RLP.encode(payload)), this._verbose) const debugMsg = `Send ${messageName} message to ${this._peer._socket.remoteAddress}:${this._peer._socket.remotePort}: ${logData}` this.debug(messageName, debugMsg) @@ -241,7 +244,7 @@ export class LES extends Protocol { throw new Error(`Unknown code ${code}`) } - payload = Buffer.from(RLP.encode(payload)) + payload = RLP.encode(payload) // Use snappy compression if peer supports DevP2P >=v5 if (this._peer._hello !== null && this._peer._hello.protocolVersion >= 5) { @@ -259,22 +262,22 @@ export class LES extends Protocol { export namespace LES { export interface Status { [key: string]: any - protocolVersion: Buffer - networkId: Buffer - headTd: Buffer - headHash: Buffer - headNum: Buffer - genesisHash: Buffer - serveHeaders: Buffer - serveChainSince: Buffer - serveStateSince: Buffer - txRelay: Buffer - 'flowControl/BL': Buffer - 'flowControl/MRR': Buffer - 'flowControl/MRC': Buffer - announceType: Buffer - forkID: [Buffer, Buffer] - recentTxLookup: Buffer + protocolVersion: Uint8Array + networkId: Uint8Array + headTd: Uint8Array + headHash: Uint8Array + headNum: Uint8Array + genesisHash: Uint8Array + serveHeaders: Uint8Array + serveChainSince: Uint8Array + serveStateSince: Uint8Array + txRelay: Uint8Array + 'flowControl/BL': Uint8Array + 'flowControl/MRR': Uint8Array + 'flowControl/MRC': Uint8Array + announceType: Uint8Array + forkID: [Uint8Array, Uint8Array] + recentTxLookup: Uint8Array } export enum MESSAGE_CODES { diff --git a/packages/devp2p/src/protocol/protocol.ts b/packages/devp2p/src/protocol/protocol.ts index 5f239ed963..08e7624075 100644 --- a/packages/devp2p/src/protocol/protocol.ts +++ b/packages/devp2p/src/protocol/protocol.ts @@ -16,7 +16,7 @@ export enum EthProtocol { // What does this represent? type MessageCodes = { [key: number | string]: number | string } -export type SendMethod = (code: number, data: Buffer) => any +export type SendMethod = (code: number, data: Uint8Array) => any export class Protocol extends EventEmitter { _version: number diff --git a/packages/devp2p/src/protocol/snap.ts b/packages/devp2p/src/protocol/snap.ts index a3c03c11c7..accead154d 100644 --- a/packages/devp2p/src/protocol/snap.ts +++ b/packages/devp2p/src/protocol/snap.ts @@ -1,4 +1,5 @@ import { RLP, utils } from '@ethereumjs/rlp' +import { bytesToHex } from 'ethereum-cryptography/utils' import * as snappy from 'snappyjs' import { formatLogData } from '../util' @@ -21,7 +22,7 @@ export class SNAP extends Protocol { // Note, this needs optimization, see issue #1882 const debugMsg = `Received ${messageName} message from ${this._peer._socket.remoteAddress}:${this._peer._socket.remotePort}` - const logData = formatLogData(data.toString('hex'), this._verbose) + const logData = formatLogData(bytesToHex(data), this._verbose) this.debug(messageName, `${debugMsg}: ${logData}`) switch (code) { diff --git a/packages/devp2p/src/rlpx/ecies.ts b/packages/devp2p/src/rlpx/ecies.ts index 0df8f1f7c2..5c7e540042 100644 --- a/packages/devp2p/src/rlpx/ecies.ts +++ b/packages/devp2p/src/rlpx/ecies.ts @@ -1,16 +1,16 @@ import { RLP } from '@ethereumjs/rlp' -import { bufArrToArr } from '@ethereumjs/util' +import { bytesToInt, concatBytes, intToBytes } from '@ethereumjs/util' import * as crypto from 'crypto' import { debug as createDebugLogger } from 'debug' +import { getRandomBytesSync } from 'ethereum-cryptography/random' import { getPublicKey } from 'ethereum-cryptography/secp256k1' import { ecdh, ecdsaRecover, ecdsaSign } from 'ethereum-cryptography/secp256k1-compat' +import { hexToBytes } from 'ethereum-cryptography/utils' import { assertEq, - buffer2int, genPrivateKey, id2pk, - int2buffer, keccak256, pk2id, unstrictDecode, @@ -23,15 +23,15 @@ type Decipher = crypto.Decipher const debug = createDebugLogger('devp2p:rlpx:peer') -function ecdhX(publicKey: Buffer, privateKey: Buffer) { +function ecdhX(publicKey: Uint8Array, privateKey: Uint8Array) { // return (publicKey * privateKey).x function hashfn(x: Uint8Array, y: Uint8Array) { const pubKey = new Uint8Array(33) pubKey[0] = (y[31] & 1) === 0 ? 0x02 : 0x03 pubKey.set(x, 1) - return pubKey.slice(1) + return pubKey.subarray(1) } - return Buffer.from(ecdh(publicKey, privateKey, { hashfn }, Buffer.alloc(32))) + return ecdh(publicKey, privateKey, { hashfn }, new Uint8Array(32)) } // a straight rip from python interop w/go ecies implementation @@ -41,121 +41,125 @@ function ecdhX(publicKey: Buffer, privateKey: Buffer) { // https://github.com/ethereum/pydevp2p/blob/master/devp2p/crypto.py#L295 // https://github.com/ethereum/go-ethereum/blob/fe532a98f9f32bb81ef0d8d013cf44327830d11e/crypto/ecies/ecies.go#L165 // https://github.com/ethereum/cpp-ethereum/blob/develop/libdevcrypto/CryptoPP.cpp#L36 -function concatKDF(keyMaterial: Buffer, keyLength: number) { +function concatKDF(keyMaterial: Uint8Array, keyLength: number) { const SHA256BlockSize = 64 const reps = ((keyLength + 7) * 8) / (SHA256BlockSize * 8) - const buffers = [] - for (let counter = 0, tmp = Buffer.allocUnsafe(4); counter <= reps; ) { + const bytes = [] + for (let counter = 0, tmp = new Uint8Array(4); counter <= reps; ) { counter += 1 - tmp.writeUInt32BE(counter, 0) - buffers.push(crypto.createHash('sha256').update(tmp).update(keyMaterial).digest()) + new DataView(tmp.buffer).setUint32(0, counter) + bytes.push( + Uint8Array.from(crypto.createHash('sha256').update(tmp).update(keyMaterial).digest()) + ) } - return Buffer.concat(buffers).slice(0, keyLength) + return concatBytes(...bytes).subarray(0, keyLength) } export class ECIES { - _privateKey: Buffer - _publicKey: Buffer - _remotePublicKey: Buffer | null - _nonce: Buffer - _remoteNonce: Buffer | null = null - _initMsg: Buffer | null | undefined = null - _remoteInitMsg: Buffer | null = null + _privateKey: Uint8Array + _publicKey: Uint8Array + _remotePublicKey: Uint8Array | null + _nonce: Uint8Array + _remoteNonce: Uint8Array | null = null + _initMsg: Uint8Array | null | undefined = null + _remoteInitMsg: Uint8Array | null = null _gotEIP8Auth: boolean = false _gotEIP8Ack: boolean = false _ingressAes: Decipher | null = null _egressAes: Decipher | null = null _ingressMac: MAC | null = null _egressMac: MAC | null = null - _ephemeralPrivateKey: Buffer - _ephemeralPublicKey: Buffer - _remoteEphemeralPublicKey: Buffer | null = null // we don't need store this key, but why don't? - _ephemeralSharedSecret: Buffer | null = null + _ephemeralPrivateKey: Uint8Array + _ephemeralPublicKey: Uint8Array + _remoteEphemeralPublicKey: Uint8Array | null = null // we don't need store this key, but why don't? + _ephemeralSharedSecret: Uint8Array | null = null _bodySize: number | null = null - constructor(privateKey: Buffer, id: Buffer, remoteId: Buffer) { + constructor(privateKey: Uint8Array, id: Uint8Array, remoteId: Uint8Array) { this._privateKey = privateKey this._publicKey = id2pk(id) this._remotePublicKey = remoteId !== null ? id2pk(remoteId) : null - this._nonce = crypto.randomBytes(32) + this._nonce = getRandomBytesSync(32) this._ephemeralPrivateKey = genPrivateKey() - this._ephemeralPublicKey = Buffer.from(getPublicKey(this._ephemeralPrivateKey, false)) + this._ephemeralPublicKey = getPublicKey(this._ephemeralPrivateKey, false) } - _encryptMessage(data: Buffer, sharedMacData: Buffer | null = null): Buffer | undefined { + _encryptMessage( + data: Uint8Array, + sharedMacData: Uint8Array | null = null + ): Uint8Array | undefined { const privateKey = genPrivateKey() if (!this._remotePublicKey) return const x = ecdhX(this._remotePublicKey, privateKey) const key = concatKDF(x, 32) - const ekey = key.slice(0, 16) // encryption key - const mkey = crypto.createHash('sha256').update(key.slice(16, 32)).digest() // MAC key + const ekey = key.subarray(0, 16) // encryption key + const mkey = crypto.createHash('sha256').update(key.subarray(16, 32)).digest() // MAC key // encrypt - const IV = crypto.randomBytes(16) + const IV = getRandomBytesSync(16) const cipher = crypto.createCipheriv('aes-128-ctr', ekey, IV) - const encryptedData = cipher.update(data) - const dataIV = Buffer.concat([IV, encryptedData]) + const encryptedData = Uint8Array.from(cipher.update(data)) + const dataIV = concatBytes(IV, encryptedData) // create tag if (!sharedMacData) { - sharedMacData = Buffer.from([]) + sharedMacData = Uint8Array.from([]) } - const tag = crypto - .createHmac('sha256', mkey) - .update(Buffer.concat([dataIV, sharedMacData])) - .digest() + const tag = Uint8Array.from( + crypto.createHmac('sha256', mkey).update(concatBytes(dataIV, sharedMacData)).digest() + ) const publicKey = getPublicKey(privateKey, false) - return Buffer.concat([publicKey, dataIV, tag]) + return concatBytes(publicKey, dataIV, tag) } - _decryptMessage(data: Buffer, sharedMacData: Buffer | null = null): Buffer { + _decryptMessage(data: Uint8Array, sharedMacData: Uint8Array | null = null): Uint8Array { assertEq( - data.slice(0, 1), - Buffer.from('04', 'hex'), + data.subarray(0, 1), + hexToBytes('04'), 'wrong ecies header (possible cause: EIP8 upgrade)', debug ) - const publicKey = data.slice(0, 65) - const dataIV = data.slice(65, -32) - const tag = data.slice(-32) + const publicKey = data.subarray(0, 65) + const dataIV = data.subarray(65, -32) + const tag = data.subarray(-32) // derive keys const x = ecdhX(publicKey, this._privateKey) const key = concatKDF(x, 32) - const ekey = key.slice(0, 16) // encryption key - const mkey = crypto.createHash('sha256').update(key.slice(16, 32)).digest() // MAC key + const ekey = key.subarray(0, 16) // encryption key + const mkey = Uint8Array.from(crypto.createHash('sha256').update(key.subarray(16, 32)).digest()) // MAC key // check the tag if (!sharedMacData) { - sharedMacData = Buffer.from([]) + sharedMacData = Uint8Array.from([]) } const _tag = crypto .createHmac('sha256', mkey) - .update(Buffer.concat([dataIV, sharedMacData])) + .update(concatBytes(dataIV, sharedMacData)) .digest() assertEq(_tag, tag, 'should have valid tag', debug) // decrypt data - const IV = dataIV.slice(0, 16) - const encryptedData = dataIV.slice(16) + const IV = dataIV.subarray(0, 16) + const encryptedData = dataIV.subarray(16) const decipher = crypto.createDecipheriv('aes-128-ctr', ekey, IV) - return decipher.update(encryptedData) + return Uint8Array.from(decipher.update(encryptedData)) } - _setupFrame(remoteData: Buffer, incoming: boolean): void { + _setupFrame(remoteData: Uint8Array, incoming: boolean): void { if (!this._remoteNonce) return const nonceMaterial = incoming - ? Buffer.concat([this._nonce, this._remoteNonce]) - : Buffer.concat([this._remoteNonce, this._nonce]) + ? concatBytes(this._nonce, this._remoteNonce) + : concatBytes(this._remoteNonce, this._nonce) const hNonce = keccak256(nonceMaterial) if (!this._ephemeralSharedSecret) return - const IV = Buffer.allocUnsafe(16).fill(0x00) + const IV = new Uint8Array(16).fill(0x00) const sharedSecret = keccak256(this._ephemeralSharedSecret, hNonce) const aesSecret = keccak256(this._ephemeralSharedSecret, sharedSecret) @@ -164,11 +168,11 @@ export class ECIES { const macSecret = keccak256(this._ephemeralSharedSecret, aesSecret) this._ingressMac = new MAC(macSecret) - this._ingressMac.update(Buffer.concat([xor(macSecret, this._nonce), remoteData])) + this._ingressMac.update(concatBytes(xor(macSecret, this._nonce), remoteData)) this._egressMac = new MAC(macSecret) if (this._initMsg === null || this._initMsg === undefined) return - this._egressMac.update(Buffer.concat([xor(macSecret, this._remoteNonce), this._initMsg])) + this._egressMac.update(concatBytes(xor(macSecret, this._remoteNonce), this._initMsg)) } createAuthEIP8() { @@ -176,44 +180,47 @@ export class ECIES { const x = ecdhX(this._remotePublicKey, this._privateKey) const sig = ecdsaSign(xor(x, this._nonce), this._ephemeralPrivateKey) const data = [ - Buffer.concat([Buffer.from(sig.signature), Buffer.from([sig.recid])]), + concatBytes(sig.signature, Uint8Array.from([sig.recid])), // keccak256(pk2id(this._ephemeralPublicKey)), pk2id(this._publicKey), this._nonce, - Buffer.from([0x04]), + Uint8Array.from([0x04]), ] - const dataRLP = Buffer.from(RLP.encode(bufArrToArr(data))) - const pad = crypto.randomBytes(100 + Math.floor(Math.random() * 151)) // Random padding between 100, 250 - const authMsg = Buffer.concat([dataRLP, pad]) + const dataRLP = RLP.encode(data) + const pad = getRandomBytesSync(100 + Math.floor(Math.random() * 151)) // Random padding between 100, 250 + const authMsg = concatBytes(dataRLP, pad) const overheadLength = 113 - const sharedMacData = int2buffer(authMsg.length + overheadLength) + const sharedMacData = intToBytes(authMsg.length + overheadLength) const encryptedMsg = this._encryptMessage(authMsg, sharedMacData) if (!encryptedMsg) return - this._initMsg = Buffer.concat([sharedMacData, encryptedMsg]) + this._initMsg = concatBytes(sharedMacData, encryptedMsg) return this._initMsg } - createAuthNonEIP8(): Buffer | undefined { + createAuthNonEIP8(): Uint8Array | undefined { if (!this._remotePublicKey) return const x = ecdhX(this._remotePublicKey, this._privateKey) const sig = ecdsaSign(xor(x, this._nonce), this._ephemeralPrivateKey) - const data = Buffer.concat([ - Buffer.from(sig.signature), - Buffer.from([sig.recid]), + const data = concatBytes( + sig.signature, + Uint8Array.from([sig.recid]), keccak256(pk2id(this._ephemeralPublicKey)), pk2id(this._publicKey), this._nonce, - Buffer.from([0x00]), - ]) + Uint8Array.from([0x00]) + ) this._initMsg = this._encryptMessage(data) return this._initMsg } - parseAuthPlain(data: Buffer, sharedMacData: Buffer | null = null): Buffer | undefined { - const prefix = sharedMacData !== null ? sharedMacData : Buffer.from([]) - this._remoteInitMsg = Buffer.concat([prefix, data]) + parseAuthPlain( + data: Uint8Array, + sharedMacData: Uint8Array | null = null + ): Uint8Array | undefined { + const prefix = sharedMacData !== null ? sharedMacData : new Uint8Array() + this._remoteInitMsg = concatBytes(prefix, data) const decrypted = this._decryptMessage(data, sharedMacData) let signature = null @@ -225,15 +232,15 @@ export class ECIES { if (!this._gotEIP8Auth) { assertEq(decrypted.length, 194, 'invalid packet length', debug) - signature = decrypted.slice(0, 64) + signature = decrypted.subarray(0, 64) recoveryId = decrypted[64] - heid = decrypted.slice(65, 97) // 32 bytes - remotePublicKey = id2pk(decrypted.slice(97, 161)) - nonce = decrypted.slice(161, 193) + heid = decrypted.subarray(65, 97) // 32 bytes + remotePublicKey = id2pk(decrypted.subarray(97, 161)) + nonce = decrypted.subarray(161, 193) } else { - const decoded = unstrictDecode(decrypted) as Buffer[] + const decoded = unstrictDecode(decrypted) as Uint8Array[] - signature = decoded[0].slice(0, 64) + signature = decoded[0].subarray(0, 64) recoveryId = decoded[0][64] remotePublicKey = id2pk(decoded[1]) nonce = decoded[2] @@ -249,8 +256,11 @@ export class ECIES { if (this._remoteNonce === null) { return } - this._remoteEphemeralPublicKey = Buffer.from( - ecdsaRecover(signature, recoveryId, xor(x, this._remoteNonce), false) + this._remoteEphemeralPublicKey = ecdsaRecover( + signature, + recoveryId, + xor(x, this._remoteNonce), + false ) if (this._remoteEphemeralPublicKey === null) return @@ -265,31 +275,31 @@ export class ECIES { } } - parseAuthEIP8(data: Buffer): void { - const size = buffer2int(data.slice(0, 2)) + 2 + parseAuthEIP8(data: Uint8Array): void { + const size = bytesToInt(data.subarray(0, 2)) + 2 assertEq(data.length, size, 'message length different from specified size (EIP8)', debug) - this.parseAuthPlain(data.slice(2), data.slice(0, 2)) + this.parseAuthPlain(data.subarray(2), data.subarray(0, 2)) } - createAckEIP8(): Buffer | undefined { - const data = [pk2id(this._ephemeralPublicKey), this._nonce, Buffer.from([0x04])] + createAckEIP8(): Uint8Array | undefined { + const data = [pk2id(this._ephemeralPublicKey), this._nonce, Uint8Array.from([0x04])] - const dataRLP = Buffer.from(RLP.encode(bufArrToArr(data))) - const pad = crypto.randomBytes(100 + Math.floor(Math.random() * 151)) // Random padding between 100, 250 - const ackMsg = Buffer.concat([dataRLP, pad]) + const dataRLP = RLP.encode(data) + const pad = getRandomBytesSync(100 + Math.floor(Math.random() * 151)) // Random padding between 100, 250 + const ackMsg = concatBytes(dataRLP, pad) const overheadLength = 113 - const sharedMacData = int2buffer(ackMsg.length + overheadLength) + const sharedMacData = intToBytes(ackMsg.length + overheadLength) const encryptedMsg = this._encryptMessage(ackMsg, sharedMacData) if (!encryptedMsg) return - this._initMsg = Buffer.concat([sharedMacData, encryptedMsg]) + this._initMsg = concatBytes(sharedMacData, encryptedMsg) if (!this._remoteInitMsg) return this._setupFrame(this._remoteInitMsg, true) return this._initMsg } - createAckOld(): Buffer | undefined { - const data = Buffer.concat([pk2id(this._ephemeralPublicKey), this._nonce, Buffer.from([0x00])]) + createAckOld(): Uint8Array | undefined { + const data = concatBytes(pk2id(this._ephemeralPublicKey), this._nonce, new Uint8Array([0x00])) this._initMsg = this._encryptMessage(data) @@ -298,7 +308,7 @@ export class ECIES { return this._initMsg } - parseAckPlain(data: Buffer, sharedMacData: Buffer | null = null): void { + parseAckPlain(data: Uint8Array, sharedMacData: Uint8Array | null = null): void { const decrypted = this._decryptMessage(data, sharedMacData) let remoteEphemeralPublicKey = null @@ -308,10 +318,10 @@ export class ECIES { assertEq(decrypted.length, 97, 'invalid packet length', debug) assertEq(decrypted[96], 0, 'invalid postfix', debug) - remoteEphemeralPublicKey = id2pk(decrypted.slice(0, 64)) - remoteNonce = decrypted.slice(64, 96) + remoteEphemeralPublicKey = id2pk(decrypted.subarray(0, 64)) + remoteNonce = decrypted.subarray(64, 96) } else { - const decoded = unstrictDecode(decrypted) as Buffer[] + const decoded = unstrictDecode(decrypted) as Uint8Array[] remoteEphemeralPublicKey = id2pk(decoded[0]) remoteNonce = decoded[1] @@ -323,74 +333,74 @@ export class ECIES { this._ephemeralSharedSecret = ecdhX(this._remoteEphemeralPublicKey, this._ephemeralPrivateKey) if (!sharedMacData) { - sharedMacData = Buffer.from([]) + sharedMacData = Uint8Array.from([]) } - this._setupFrame(Buffer.concat([sharedMacData, data]), false) + this._setupFrame(concatBytes(sharedMacData, data), false) } - parseAckEIP8(data: Buffer): void { - const size = buffer2int(data.slice(0, 2)) + 2 + parseAckEIP8(data: Uint8Array): void { + const size = bytesToInt(data.subarray(0, 2)) + 2 assertEq(data.length, size, 'message length different from specified size (EIP8)', debug) - this.parseAckPlain(data.slice(2), data.slice(0, 2)) + this.parseAckPlain(data.subarray(2), data.subarray(0, 2)) } - createHeader(size: number): Buffer | undefined { - const bufSize = zfill(int2buffer(size), 3) - const headerData = Buffer.from(RLP.encode([0, 0])) // [capability-id, context-id] (currently unused in spec) - let header = Buffer.concat([bufSize, headerData]) + createHeader(size: number): Uint8Array | undefined { + const bufSize = zfill(intToBytes(size), 3) + const headerData = RLP.encode([0, 0]) // [capability-id, context-id] (currently unused in spec) + let header = concatBytes(bufSize, headerData) header = zfill(header, 16, false) if (!this._egressAes) return - header = this._egressAes.update(header) + header = Uint8Array.from(this._egressAes.update(header)) if (!this._egressMac) return this._egressMac.updateHeader(header) - const tag = this._egressMac.digest() + const tag = Uint8Array.from(this._egressMac.digest()) - return Buffer.concat([header, tag]) + return concatBytes(header, tag) } - parseHeader(data: Buffer): number | undefined { + parseHeader(data: Uint8Array): number | undefined { // parse header - let header = data.slice(0, 16) - const mac = data.slice(16, 32) + let header = data.subarray(0, 16) + const mac = data.subarray(16, 32) if (!this._ingressMac) return this._ingressMac.updateHeader(header) - const _mac = this._ingressMac.digest() + const _mac = Uint8Array.from(this._ingressMac.digest()) assertEq(_mac, mac, 'Invalid MAC', debug) if (!this._ingressAes) return - header = this._ingressAes.update(header) - this._bodySize = buffer2int(header.slice(0, 3)) + header = Uint8Array.from(this._ingressAes.update(header)) + this._bodySize = bytesToInt(header.subarray(0, 3)) return this._bodySize } - createBody(data: Buffer): Buffer | undefined { + createBody(data: Uint8Array): Uint8Array | undefined { data = zfill(data, Math.ceil(data.length / 16) * 16, false) if (!this._egressAes) return - const encryptedData = this._egressAes.update(data) + const encryptedData = Uint8Array.from(this._egressAes.update(data)) if (!this._egressMac) return this._egressMac.updateBody(encryptedData) - const tag = this._egressMac.digest() - return Buffer.concat([encryptedData, tag]) + const tag = Uint8Array.from(this._egressMac.digest()) + return concatBytes(encryptedData, tag) } - parseBody(data: Buffer): Buffer | undefined { + parseBody(data: Uint8Array): Uint8Array | undefined { if (this._bodySize === null) throw new Error('need to parse header first') - const body = data.slice(0, -16) - const mac = data.slice(-16) + const body = data.subarray(0, -16) + const mac = data.subarray(-16) if (!this._ingressMac) return this._ingressMac.updateBody(body) - const _mac = this._ingressMac.digest() + const _mac = Uint8Array.from(this._ingressMac.digest()) assertEq(_mac, mac, 'Invalid MAC', debug) const size = this._bodySize this._bodySize = null if (!this._ingressAes) return - return this._ingressAes.update(body).slice(0, size) + return Uint8Array.from(this._ingressAes.update(body)).subarray(0, size) } } diff --git a/packages/devp2p/src/rlpx/mac.ts b/packages/devp2p/src/rlpx/mac.ts index a19c7a3b08..8a50c89c8f 100644 --- a/packages/devp2p/src/rlpx/mac.ts +++ b/packages/devp2p/src/rlpx/mac.ts @@ -7,23 +7,23 @@ export type Hash = ReturnType export class MAC { _hash: Hash - _secret: Buffer - constructor(secret: Buffer) { + _secret: Uint8Array + constructor(secret: Uint8Array) { this._hash = keccak256.create() this._secret = secret } - update(data: Buffer | string) { + update(data: Uint8Array | string) { this._hash.update(data) } - updateHeader(data: Buffer | string) { + updateHeader(data: Uint8Array | string) { const aes = createCipheriv('aes-256-ecb', this._secret, '') const encrypted = aes.update(this.digest()) this._hash.update(xor(encrypted, data)) } - updateBody(data: Buffer | string) { + updateBody(data: Uint8Array | string) { this._hash.update(data) const prev = this.digest() const aes = createCipheriv('aes-256-ecb', this._secret, '') @@ -32,6 +32,6 @@ export class MAC { } digest() { - return Buffer.from(this._hash.clone().digest().slice(0, 16)) + return Uint8Array.from(this._hash.clone().digest().subarray(0, 16)) } } diff --git a/packages/devp2p/src/rlpx/peer.ts b/packages/devp2p/src/rlpx/peer.ts index 152f8f8e1d..06adf22e37 100644 --- a/packages/devp2p/src/rlpx/peer.ts +++ b/packages/devp2p/src/rlpx/peer.ts @@ -1,12 +1,19 @@ import { RLP } from '@ethereumjs/rlp' -import { arrToBufArr, bufArrToArr } from '@ethereumjs/util' -import BufferList = require('bl') +import { + bytesToHex, + bytesToInt, + concatBytes, + equalsBytes, + intToBytes, + utf8ToBytes, +} from '@ethereumjs/util' import { debug as createDebugLogger } from 'debug' +import { bytesToUtf8, hexToBytes } from 'ethereum-cryptography/utils' import { EventEmitter } from 'events' import ms = require('ms') import * as snappy from 'snappyjs' -import { buffer2int, devp2pDebug, formatLogData, int2buffer } from '../util' +import { devp2pDebug, formatLogData } from '../util' import { ECIES } from './ecies' @@ -47,11 +54,11 @@ export enum DISCONNECT_REASONS { } export type HelloMsg = { - 0: Buffer - 1: Buffer - 2: Buffer[][] - 3: Buffer - 4: Buffer + 0: Uint8Array + 1: Uint8Array + 2: Uint8Array[][] + 3: Uint8Array + 4: Uint8Array length: 5 } @@ -77,25 +84,25 @@ export interface Hello { clientId: string capabilities: Capabilities[] port: number - id: Buffer + id: Uint8Array } export class Peer extends EventEmitter { - _clientId: Buffer + _clientId: Uint8Array _capabilities?: Capabilities[] _common: Common _port: number - _id: Buffer + _id: Uint8Array _remoteClientIdFilter: any - _remoteId: Buffer - _EIP8: Buffer | boolean + _remoteId: Uint8Array + _EIP8: Uint8Array | boolean _eciesSession: ECIES _state: string _weHello: HelloMsg | null _hello: Hello | null _nextPacketSize: number _socket: Socket - _socketData: BufferList + _socketData: Uint8Array _pingIntervalId: NodeJS.Timeout | null _pingTimeoutId: NodeJS.Timeout | null _closed: boolean @@ -135,7 +142,7 @@ export class Peer extends EventEmitter { // socket this._socket = options.socket - this._socketData = new BufferList() + this._socketData = new Uint8Array() this._socket.on('data', this._onSocketData.bind(this)) this._socket.on('error', (err: Error) => this.emit('error', err)) this._socket.once('close', this._onSocketClose.bind(this)) @@ -208,10 +215,10 @@ export class Peer extends EventEmitter { * @param code * @param data */ - _sendMessage(code: number, data: Buffer) { + _sendMessage(code: number, data: Uint8Array) { if (this._closed) return false - const msg = Buffer.concat([Buffer.from(RLP.encode(code)), data]) + const msg = concatBytes(RLP.encode(code), data) const header = this._eciesSession.createHeader(msg.length) if (!header || this._socket.destroyed) return this._socket.write(header) @@ -236,22 +243,19 @@ export class Peer extends EventEmitter { // TODO: Remove when we can also serve snap requests from other peers .filter((c) => c.name !== 'snap') .map((c) => `${c.name}${c.version}`) - .join(',')} clientId=${this._clientId}` + .join(',')} clientId=${bytesToUtf8(this._clientId)}` this.debug('HELLO', debugMsg) const payload: HelloMsg = [ - int2buffer(BASE_PROTOCOL_VERSION), + intToBytes(BASE_PROTOCOL_VERSION), this._clientId, - this._capabilities!.map((c) => [Buffer.from(c.name), int2buffer(c.version)]), - this._port === null ? Buffer.allocUnsafe(0) : int2buffer(this._port), + this._capabilities!.map((c) => [utf8ToBytes(c.name), intToBytes(c.version)]), + this._port === null ? new Uint8Array(0) : intToBytes(this._port), this._id, ] if (!this._closed) { if ( - this._sendMessage( - PREFIXES.HELLO, - Buffer.from(RLP.encode(bufArrToArr(payload as unknown as Buffer[]))) - ) === true + this._sendMessage(PREFIXES.HELLO, RLP.encode(payload as never as Uint8Array[])) === true ) { this._weHello = payload } @@ -269,7 +273,7 @@ export class Peer extends EventEmitter { const reasonName = this.getDisconnectPrefix(reason) const debugMsg = `Send DISCONNECT to ${this._socket.remoteAddress}:${this._socket.remotePort} (reason: ${reasonName})` this.debug('DISCONNECT', debugMsg, reasonName) - const data = Buffer.from(RLP.encode(reason)) + const data = RLP.encode(reason) if (this._sendMessage(PREFIXES.DISCONNECT, data) !== true) return this._disconnectReason = reason @@ -284,7 +288,7 @@ export class Peer extends EventEmitter { _sendPing() { const debugMsg = `Send PING to ${this._socket.remoteAddress}:${this._socket.remotePort}` this.debug('PING', debugMsg) - let data = Buffer.from(RLP.encode([])) + let data = RLP.encode([]) if (this._hello !== null && this._hello.protocolVersion >= 5) { data = snappy.compress(data) } @@ -303,7 +307,7 @@ export class Peer extends EventEmitter { _sendPong() { const debugMsg = `Send PONG to ${this._socket.remoteAddress}:${this._socket.remotePort}` this.debug('PONG', debugMsg) - let data = Buffer.from(RLP.encode([])) + let data = RLP.encode([]) if (this._hello !== null && this._hello.protocolVersion >= 5) { data = snappy.compress(data) @@ -316,13 +320,13 @@ export class Peer extends EventEmitter { */ _handleAuth() { const bytesCount = this._nextPacketSize - const parseData = this._socketData.slice(0, bytesCount) + const parseData = this._socketData.subarray(0, bytesCount) if (!this._eciesSession._gotEIP8Auth) { - if (parseData.slice(0, 1) === Buffer.from('04', 'hex')) { + if (parseData.subarray(0, 1) === hexToBytes('04')) { this._eciesSession.parseAuthPlain(parseData) } else { this._eciesSession._gotEIP8Auth = true - this._nextPacketSize = buffer2int(this._socketData.slice(0, 2)) + 2 + this._nextPacketSize = bytesToInt(this._socketData.subarray(0, 2)) + 2 return } } else { @@ -331,7 +335,7 @@ export class Peer extends EventEmitter { this._state = 'Header' this._nextPacketSize = 32 process.nextTick(() => this._sendAck()) - this._socketData.consume(bytesCount) + this._socketData = this._socketData.subarray(bytesCount) } /** @@ -339,16 +343,16 @@ export class Peer extends EventEmitter { */ _handleAck() { const bytesCount = this._nextPacketSize - const parseData = this._socketData.slice(0, bytesCount) + const parseData = this._socketData.subarray(0, bytesCount) if (!this._eciesSession._gotEIP8Ack) { - if (parseData.slice(0, 1) === Buffer.from('04', 'hex')) { + if (parseData.subarray(0, 1) === hexToBytes('04')) { this._eciesSession.parseAckPlain(parseData) this._logger( `Received ack (old format) from ${this._socket.remoteAddress}:${this._socket.remotePort}` ) } else { this._eciesSession._gotEIP8Ack = true - this._nextPacketSize = buffer2int(this._socketData.slice(0, 2)) + 2 + this._nextPacketSize = bytesToInt(this._socketData.subarray(0, 2)) + 2 return } } else { @@ -360,7 +364,7 @@ export class Peer extends EventEmitter { this._state = 'Header' this._nextPacketSize = 32 process.nextTick(() => this._sendHello()) - this._socketData.consume(bytesCount) + this._socketData = this._socketData.subarray(bytesCount) } /** @@ -368,12 +372,12 @@ export class Peer extends EventEmitter { */ _handleHello(payload: any) { this._hello = { - protocolVersion: buffer2int(payload[0]), - clientId: payload[1].toString(), + protocolVersion: bytesToInt(payload[0]), + clientId: bytesToUtf8(payload[1]), capabilities: payload[2].map((item: any) => { - return { name: item[0].toString(), version: buffer2int(item[1]) } + return { name: bytesToUtf8(item[0]), version: bytesToInt(item[1]) } }), - port: buffer2int(payload[3]), + port: bytesToInt(payload[3]), id: payload[4], } @@ -385,8 +389,8 @@ export class Peer extends EventEmitter { this.debug('HELLO', debugMsg) if (this._remoteId === null) { - this._remoteId = Buffer.from(this._hello.id) - } else if (!this._remoteId.equals(this._hello.id)) { + this._remoteId = this._hello.id + } else if (!equalsBytes(this._remoteId, this._hello.id)) { return this.disconnect(DISCONNECT_REASONS.INVALID_IDENTITY) } @@ -418,7 +422,7 @@ export class Peer extends EventEmitter { // The send method handed over to the subprotocol object (e.g. an `ETH` instance). // The subprotocol is then calling into the lower level method // (e.g. `ETH` calling into `Peer._sendMessage()`). - const sendMethod = (code: number, data: Buffer) => { + const sendMethod = (code: number, data: Uint8Array) => { if (code > obj.length) throw new Error('Code out of range') this._sendMessage(_offset + code, data) } @@ -447,10 +451,11 @@ export class Peer extends EventEmitter { */ _handleDisconnect(payload: any) { this._closed = true - // When `payload` is from rlpx it is `Buffer` and when from subprotocol it is `[Buffer]` - this._disconnectReason = Buffer.isBuffer(payload) - ? buffer2int(payload) - : buffer2int(payload[0] ?? Buffer.from([0])) + // When `payload` is from rlpx it is `Uint8Array` and when from subprotocol it is `[Uint8Array]` + this._disconnectReason = + payload instanceof Uint8Array + ? bytesToInt(payload) + : bytesToInt(payload[0] ?? Uint8Array.from([0])) const reason = DISCONNECT_REASONS[this._disconnectReason as number] const debugMsg = `DISCONNECT reason: ${reason} ${this._socket.remoteAddress}:${this._socket.remotePort}` this.debug('DISCONNECT', debugMsg, reason) @@ -477,7 +482,7 @@ export class Peer extends EventEmitter { * @param code * @param msg */ - _handleMessage(code: PREFIXES, msg: Buffer) { + _handleMessage(code: PREFIXES, msg: Uint8Array) { switch (code) { case PREFIXES.HELLO: this._handleHello(msg) @@ -499,7 +504,7 @@ export class Peer extends EventEmitter { */ _handleHeader() { const bytesCount = this._nextPacketSize - const parseData = this._socketData.slice(0, bytesCount) + const parseData = this._socketData.subarray(0, bytesCount) this._logger(`Received header ${this._socket.remoteAddress}:${this._socket.remotePort}`) const size = this._eciesSession.parseHeader(parseData) if (size === undefined) { @@ -510,7 +515,7 @@ export class Peer extends EventEmitter { this._state = 'Body' this._nextPacketSize = size + 16 if (size % 16 > 0) this._nextPacketSize += 16 - (size % 16) - this._socketData.consume(bytesCount) + this._socketData = this._socketData.subarray(bytesCount) } /** @@ -518,7 +523,7 @@ export class Peer extends EventEmitter { */ _handleBody() { const bytesCount = this._nextPacketSize - const parseData = this._socketData.slice(0, bytesCount) + const parseData = this._socketData.subarray(0, bytesCount) const body = this._eciesSession.parseBody(parseData) if (!body) { this._logger('empty body!') @@ -526,7 +531,7 @@ export class Peer extends EventEmitter { } this._logger( `Received body ${this._socket.remoteAddress}:${this._socket.remotePort} ${formatLogData( - body.toString('hex'), + bytesToHex(body), verbose )}` ) @@ -557,7 +562,7 @@ export class Peer extends EventEmitter { } try { - let payload: any = body.slice(1) + let payload: any = body.subarray(1) // Use snappy uncompression if peer supports DevP2P >=v5 let compressed = false @@ -582,13 +587,13 @@ export class Peer extends EventEmitter { // if (protocolName === 'Peer') { try { - payload = arrToBufArr(RLP.decode(Uint8Array.from(payload))) + payload = RLP.decode(Uint8Array.from(payload)) } catch (e: any) { if (msgCode === PREFIXES.DISCONNECT) { if (compressed) { - payload = arrToBufArr(RLP.decode(Uint8Array.from(origPayload))) + payload = RLP.decode(Uint8Array.from(origPayload)) } else { - payload = arrToBufArr(RLP.decode(Uint8Array.from(snappy.uncompress(payload)))) + payload = RLP.decode(snappy.uncompress(payload)) } } else { throw new Error(e) @@ -601,16 +606,16 @@ export class Peer extends EventEmitter { this._logger(`Error on peer subprotocol message handling: ${err}`) this.emit('error', err) } - this._socketData.consume(bytesCount) + this._socketData = this._socketData.subarray(bytesCount) } /** * Process socket data * @param data */ - _onSocketData(data: Buffer) { + _onSocketData(data: Uint8Array) { if (this._closed) return - this._socketData.append(data) + this._socketData = concatBytes(this._socketData, data) try { while (this._socketData.length >= this._nextPacketSize) { switch (this._state) { @@ -660,7 +665,7 @@ export class Peer extends EventEmitter { getId() { if (this._remoteId === null) return null - return Buffer.from(this._remoteId) + return this._remoteId } getHelloMessage() { diff --git a/packages/devp2p/src/rlpx/rlpx.ts b/packages/devp2p/src/rlpx/rlpx.ts index 7a5eae9136..030fdc75f1 100644 --- a/packages/devp2p/src/rlpx/rlpx.ts +++ b/packages/devp2p/src/rlpx/rlpx.ts @@ -1,12 +1,14 @@ +import { bytesToInt } from '@ethereumjs/util' import { debug as createDebugLogger } from 'debug' import { getPublicKey } from 'ethereum-cryptography/secp256k1' +import { bytesToHex, equalsBytes, hexToBytes, utf8ToBytes } from 'ethereum-cryptography/utils' import { EventEmitter } from 'events' import * as LRUCache from 'lru-cache' import ms = require('ms') import * as net from 'net' import * as os from 'os' -import { buffer2int, createDeferred, devp2pDebug, formatLogId, pk2id } from '../util' +import { createDeferred, devp2pDebug, formatLogId, pk2id } from '../util' import { DISCONNECT_REASONS, Peer } from './peer' @@ -22,7 +24,7 @@ const DEBUG_BASE_NAME = 'rlpx' const verbose = createDebugLogger('verbose').enabled export interface RLPxOptions { - clientId?: Buffer + clientId?: Uint8Array /* Timeout (default: 10s) */ timeout?: number dpt?: DPT | null @@ -35,12 +37,12 @@ export interface RLPxOptions { } export class RLPx extends EventEmitter { - _privateKey: Buffer - _id: Buffer + _privateKey: Uint8Array + _id: Uint8Array _debug: Debugger _timeout: number _maxPeers: number - _clientId: Buffer + _clientId: Uint8Array _remoteClientIdFilter?: string[] _capabilities: Capabilities[] _common: Common @@ -55,19 +57,19 @@ export class RLPx extends EventEmitter { _refillIntervalId: NodeJS.Timeout _refillIntervalSelectionCounter: number = 0 - constructor(privateKey: Buffer, options: RLPxOptions) { + constructor(privateKey: Uint8Array, options: RLPxOptions) { super() - this._privateKey = Buffer.from(privateKey) - this._id = pk2id(Buffer.from(getPublicKey(this._privateKey, false))) + this._privateKey = privateKey + this._id = pk2id(getPublicKey(this._privateKey, false)) // options this._timeout = options.timeout ?? ms('10s') this._maxPeers = options.maxPeers ?? 10 this._clientId = options.clientId - ? Buffer.from(options.clientId) - : Buffer.from(`ethereumjs-devp2p/v${pVersion}/${os.platform()}-${os.arch()}/nodejs`) + ? options.clientId + : utf8ToBytes(`ethereumjs-devp2p/v${pVersion}/${os.platform()}-${os.arch()}/nodejs`) this._remoteClientIdFilter = options.remoteClientIdFilter this._capabilities = options.capabilities @@ -84,8 +86,8 @@ export class RLPx extends EventEmitter { return } - if (this._peersLRU.has(peer.id!.toString('hex'))) return - this._peersLRU.set(peer.id!.toString('hex'), true) + if (this._peersLRU.has(bytesToHex(peer.id!))) return + this._peersLRU.set(bytesToHex(peer.id!), true) if (this._getOpenSlots() > 0) { return this._connectToPeer(peer) @@ -96,7 +98,7 @@ export class RLPx extends EventEmitter { this._dpt.on('peer:removed', (peer: PeerInfo) => { // remove from queue this._peersQueue = this._peersQueue.filter( - (item) => !(item.peer.id! as Buffer).equals(peer.id as Buffer) + (item) => !equalsBytes(item.peer.id! as Uint8Array, peer.id as Uint8Array) ) }) } @@ -135,15 +137,15 @@ export class RLPx extends EventEmitter { if (this._server) this._server.close(...args) this._server = null - for (const peerKey of this._peers.keys()) this.disconnect(Buffer.from(peerKey, 'hex')) + for (const peerKey of this._peers.keys()) this.disconnect(hexToBytes(peerKey)) } async connect(peer: PeerInfo) { if (peer.tcpPort === undefined || peer.tcpPort === null || peer.address === undefined) return this._isAliveCheck() - if (!Buffer.isBuffer(peer.id)) throw new TypeError('Expected peer.id as Buffer') - const peerKey = peer.id.toString('hex') + if (!(peer.id instanceof Uint8Array)) throw new TypeError('Expected peer.id as Uint8Array') + const peerKey = bytesToHex(peer.id) if (this._peers.has(peerKey)) throw new Error('Already connected') if (this._getOpenSlots() === 0) throw new Error('Too many peers already connected') @@ -170,8 +172,8 @@ export class RLPx extends EventEmitter { return Array.from(this._peers.values()).filter((item) => item instanceof Peer) } - disconnect(id: Buffer) { - const peer = this._peers.get(id.toString('hex')) + disconnect(id: Uint8Array) { + const peer = this._peers.get(bytesToHex(id)) if (peer instanceof Peer) peer.disconnect(DISCONNECT_REASONS.CLIENT_QUITTING) } @@ -200,7 +202,7 @@ export class RLPx extends EventEmitter { }) } - _onConnect(socket: net.Socket, peerId: Buffer | null) { + _onConnect(socket: net.Socket, peerId: Uint8Array | null) { this._debug(`connected to ${socket.remoteAddress}:${socket.remotePort}, handshake waiting..`) const peer: Peer = new Peer({ @@ -234,11 +236,11 @@ export class RLPx extends EventEmitter { } this._debug(msg) const id = peer.getId() - if (id && id.equals(this._id)) { + if (id && equalsBytes(id, this._id)) { return peer.disconnect(DISCONNECT_REASONS.SAME_IDENTITY) } - const peerKey = id!.toString('hex') + const peerKey = bytesToHex(id!) const item = this._peers.get(peerKey) if (item && item instanceof Peer) { return peer.disconnect(DISCONNECT_REASONS.ALREADY_CONNECTED) @@ -272,7 +274,7 @@ export class RLPx extends EventEmitter { const id = peer.getId() if (id) { - const peerKey = id.toString('hex') + const peerKey = bytesToHex(id) this._peers.delete(peerKey) this.emit('peer:removed', peer, reason, disconnectWe) } @@ -299,7 +301,7 @@ export class RLPx extends EventEmitter { // Randomly distributed selector based on peer ID // to decide on subdivided execution - const selector = buffer2int((item.peer.id! as Buffer).slice(0, 1)) % 10 + const selector = bytesToInt((item.peer.id! as Uint8Array).subarray(0, 1)) % 10 if (selector === this._refillIntervalSelectionCounter) { this._connectToPeer(item.peer) return false diff --git a/packages/devp2p/src/util.ts b/packages/devp2p/src/util.ts index de3f94761d..fa0afc447c 100644 --- a/packages/devp2p/src/util.ts +++ b/packages/devp2p/src/util.ts @@ -1,68 +1,51 @@ import { RLP } from '@ethereumjs/rlp' -import { arrToBufArr } from '@ethereumjs/util' import { debug as createDebugLogger } from 'debug' import { keccak256 as _keccak256 } from 'ethereum-cryptography/keccak' import { utils } from 'ethereum-cryptography/secp256k1' import { publicKeyConvert } from 'ethereum-cryptography/secp256k1-compat' +import { bytesToHex, concatBytes, equalsBytes } from 'ethereum-cryptography/utils' import type { ETH } from './protocol/eth' import type { LES } from './protocol/les' export const devp2pDebug = createDebugLogger('devp2p') -export function keccak256(...buffers: Buffer[]) { - const buffer = Buffer.concat(buffers) - return Buffer.from(_keccak256(buffer)) +export function keccak256(...bytes: Uint8Array[]) { + const allBytes = concatBytes(...bytes) + return _keccak256(allBytes) } -export function genPrivateKey(): Buffer { +export function genPrivateKey(): Uint8Array { const privateKey = utils.randomPrivateKey() - return utils.isValidPrivateKey(privateKey) ? Buffer.from(privateKey) : genPrivateKey() + return utils.isValidPrivateKey(privateKey) ? privateKey : genPrivateKey() } -export function pk2id(pk: Buffer): Buffer { +export function pk2id(pk: Uint8Array): Uint8Array { if (pk.length === 33) { - pk = Buffer.from(publicKeyConvert(pk, false)) + pk = publicKeyConvert(pk, false) } - return pk.slice(1) + return pk.subarray(1) } -export function id2pk(id: Buffer): Buffer { - return Buffer.concat([Buffer.from([0x04]), id]) +export function id2pk(id: Uint8Array): Uint8Array { + return concatBytes(Uint8Array.from([0x04]), id) } -export function int2buffer(v: number | null): Buffer { - if (v === null) { - return Buffer.alloc(0) - } - let hex = v.toString(16) - if (hex.length % 2 === 1) hex = '0' + hex - return Buffer.from(hex, 'hex') -} - -export function buffer2int(buffer: Buffer): number { - if (buffer.length === 0) return NaN - - let n = 0 - for (let i = 0; i < buffer.length; ++i) n = n * 256 + buffer[i] - return n -} - -export function zfill(buffer: Buffer, size: number, leftpad: boolean = true): Buffer { - if (buffer.length >= size) return buffer +export function zfill(bytes: Uint8Array, size: number, leftpad: boolean = true): Uint8Array { + if (bytes.length >= size) return bytes if (leftpad === undefined) leftpad = true - const pad = Buffer.allocUnsafe(size - buffer.length).fill(0x00) - return leftpad ? Buffer.concat([pad, buffer]) : Buffer.concat([buffer, pad]) + const pad = new Uint8Array(size - bytes.length).fill(0x00) + return leftpad ? concatBytes(pad, bytes) : concatBytes(bytes, pad) } -export function xor(a: Buffer, b: any): Buffer { +export function xor(a: Uint8Array, b: any): Uint8Array { const length = Math.min(a.length, b.length) - const buffer = Buffer.allocUnsafe(length) - for (let i = 0; i < length; ++i) buffer[i] = a[i] ^ b[i] - return buffer + const bytes = new Uint8Array(length) + for (let i = 0; i < length; ++i) bytes[i] = a[i] ^ b[i] + return bytes } -type assertInput = Buffer | Buffer[] | ETH.StatusMsg | LES.Status | number | null +type assertInput = Uint8Array | Uint8Array[] | ETH.StatusMsg | LES.Status | number | null export function assertEq( expected: assertInput, @@ -72,9 +55,10 @@ export function assertEq( messageName?: string ): void { let fullMsg - if (Buffer.isBuffer(expected) && Buffer.isBuffer(actual)) { - if (expected.equals(actual)) return - fullMsg = `${msg}: ${expected.toString('hex')} / ${actual.toString('hex')}` + + if (expected instanceof Uint8Array && actual instanceof Uint8Array) { + if (equalsBytes(expected, actual)) return + fullMsg = `${msg}: ${bytesToHex(expected)} / ${bytesToHex(actual)}` const debugMsg = `[ERROR] ${fullMsg}` if (messageName !== undefined) { debug(messageName, debugMsg) @@ -128,10 +112,10 @@ export function createDeferred(): Deferred { return new Deferred() } -export function unstrictDecode(value: Buffer) { +export function unstrictDecode(value: Uint8Array) { // rlp library throws on remainder.length !== 0 // this utility function bypasses that - return arrToBufArr(RLP.decode(Uint8Array.from(value), true).data) + return RLP.decode(value, true).data } // multiaddr 8.0.0 expects an Uint8Array with internal buffer starting at 0 offset @@ -139,3 +123,100 @@ export function toNewUint8Array(buf: Uint8Array): Uint8Array { const arrayBuffer = buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength) return new Uint8Array(arrayBuffer) } + +/*************************** ************************************************************/ +// Methods borrowed from `node-ip` by Fedor Indutny (https://github.com/indutny/node-ip) +// and modified to use Uint8Arrays instead of Buffers +export const ipToString = (bytes: Uint8Array, offset?: number, length?: number) => { + offset = offset !== undefined ? ~~offset : 0 + length = length ?? bytes.length - offset + + let result: any = [] + let i + if (length === 4) { + // IPv4 + for (i = 0; i < length; i++) { + result.push(bytes[offset + i]) + } + result = result.join('.') + } else if (length === 16) { + // IPv6 + for (i = 0; i < length; i += 2) { + result.push(new DataView(bytes.buffer).getUint16(offset + i).toString(16)) + } + result = result.join(':') + result = result.replace(/(^|:)0(:0)*:0(:|$)/, '$1::$3') + result = result.replace(/:{3,4}/, '::') + } + + return result +} + +const ipv4Regex = /^(\d{1,3}\.){3,3}\d{1,3}$/ +const ipv6Regex = /^(::)?(((\d{1,3}\.){3}(\d{1,3}){1})?([0-9a-f]){0,4}:{0,2}){1,8}(::)?$/i + +export const isV4Format = function (ip: string) { + return ipv4Regex.test(ip) +} + +export const isV6Format = function (ip: string) { + return ipv6Regex.test(ip) +} + +export const ipToBytes = (ip: string, bytes?: Uint8Array, offset: number = 0) => { + offset = ~~offset + + let result + + if (isV4Format(ip)) { + result = bytes ?? new Uint8Array(offset + 4) + ip.split(/\./g).map((byte) => { + result[offset++] = parseInt(byte, 10) & 0xff + }) + } else if (isV6Format(ip)) { + const sections = ip.split(':', 8) + + let i + for (i = 0; i < sections.length; i++) { + const isv4 = isV4Format(sections[i]) + let v4Bytes: Uint8Array = new Uint8Array([]) + + if (isv4) { + v4Bytes = ipToBytes(sections[i]) + sections[i] = bytesToHex(v4Bytes.subarray(0, 2)) + } + + if (v4Bytes.length > 0 && ++i < 8) { + sections.splice(i, 0, bytesToHex(v4Bytes.subarray(2, 4))) + } + } + + if (sections[0] === '') { + while (sections.length < 8) sections.unshift('0') + } else if (sections[sections.length - 1] === '') { + while (sections.length < 8) sections.push('0') + } else if (sections.length < 8) { + for (i = 0; i < sections.length && sections[i] !== ''; i++); + const argv: any = [i, 1] + for (i = 9 - sections.length; i > 0; i--) { + argv.push('0') + } + sections.splice.apply(sections, argv) + } + + result = bytes ?? new Uint8Array(offset + 16) + for (i = 0; i < sections.length; i++) { + const word = parseInt(sections[i], 16) + result[offset++] = (word >> 8) & 0xff + result[offset++] = word & 0xff + } + } + + if (!result) { + throw Error(`Invalid ip address: ${ip}`) + } + + return result +} + +/************ End of methods borrowed from `node-ip` ***************************/ diff --git a/packages/devp2p/test/dpt-message.spec.ts b/packages/devp2p/test/dpt-message.spec.ts index c1a4bd496f..f714216684 100644 --- a/packages/devp2p/test/dpt-message.spec.ts +++ b/packages/devp2p/test/dpt-message.spec.ts @@ -1,20 +1,17 @@ import { publicKeyCreate } from 'ethereum-cryptography/secp256k1-compat' +import { hexToBytes } from 'ethereum-cryptography/utils' import * as test from 'tape' import * as message from '../src/dpt/message' -const privateKey = Buffer.from( - 'b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291', - 'hex' -) -const publicKey = Buffer.from(publicKeyCreate(privateKey, false)) +const privateKey = hexToBytes('b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291') +const publicKey = publicKeyCreate(privateKey, false) test('ping packet with version 4, additional list elements', (t) => { - const buffer = Buffer.from( - 'e9614ccfd9fc3e74360018522d30e1419a143407ffcce748de3e22116b7e8dc92ff74788c0b6663aaa3d67d641936511c8f8d6ad8698b820a7cf9e1be7155e9a241f556658c55428ec0563514365799a4be2be5a685a80971ddcfa80cb422cdd0101ec04cb847f000001820cfa8215a8d790000000000000000000000000000000018208ae820d058443b9a3550102', - 'hex' + const bytes = hexToBytes( + 'e9614ccfd9fc3e74360018522d30e1419a143407ffcce748de3e22116b7e8dc92ff74788c0b6663aaa3d67d641936511c8f8d6ad8698b820a7cf9e1be7155e9a241f556658c55428ec0563514365799a4be2be5a685a80971ddcfa80cb422cdd0101ec04cb847f000001820cfa8215a8d790000000000000000000000000000000018208ae820d058443b9a3550102' ) - const msg = message.decode(buffer) + const msg = message.decode(bytes) t.same(msg.typename, 'ping') t.same(msg.data.version, 4) @@ -24,11 +21,10 @@ test('ping packet with version 4, additional list elements', (t) => { }) test('ping packet with version 555, additional list elements and additional random data:', (t) => { - const buffer = Buffer.from( - '577be4349c4dd26768081f58de4c6f375a7a22f3f7adda654d1428637412c3d7fe917cadc56d4e5e7ffae1dbe3efffb9849feb71b262de37977e7c7a44e677295680e9e38ab26bee2fcbae207fba3ff3d74069a50b902a82c9903ed37cc993c50001f83e82022bd79020010db83c4d001500000000abcdef12820cfa8215a8d79020010db885a308d313198a2e037073488208ae82823a8443b9a355c5010203040531b9019afde696e582a78fa8d95ea13ce3297d4afb8ba6433e4154caa5ac6431af1b80ba76023fa4090c408f6b4bc3701562c031041d4702971d102c9ab7fa5eed4cd6bab8f7af956f7d565ee1917084a95398b6a21eac920fe3dd1345ec0a7ef39367ee69ddf092cbfe5b93e5e568ebc491983c09c76d922dc3', - 'hex' + const bytes = hexToBytes( + '577be4349c4dd26768081f58de4c6f375a7a22f3f7adda654d1428637412c3d7fe917cadc56d4e5e7ffae1dbe3efffb9849feb71b262de37977e7c7a44e677295680e9e38ab26bee2fcbae207fba3ff3d74069a50b902a82c9903ed37cc993c50001f83e82022bd79020010db83c4d001500000000abcdef12820cfa8215a8d79020010db885a308d313198a2e037073488208ae82823a8443b9a355c5010203040531b9019afde696e582a78fa8d95ea13ce3297d4afb8ba6433e4154caa5ac6431af1b80ba76023fa4090c408f6b4bc3701562c031041d4702971d102c9ab7fa5eed4cd6bab8f7af956f7d565ee1917084a95398b6a21eac920fe3dd1345ec0a7ef39367ee69ddf092cbfe5b93e5e568ebc491983c09c76d922dc3' ) - const msg = message.decode(buffer) + const msg = message.decode(bytes) t.same(msg.typename, 'ping') t.same(msg.data.version, 555) @@ -38,11 +34,10 @@ test('ping packet with version 555, additional list elements and additional rand }) test('pong packet with additional list elements and additional random data', (t) => { - const buffer = Buffer.from( - '09b2428d83348d27cdf7064ad9024f526cebc19e4958f0fdad87c15eb598dd61d08423e0bf66b2069869e1724125f820d851c136684082774f870e614d95a2855d000f05d1648b2d5945470bc187c2d2216fbe870f43ed0909009882e176a46b0102f846d79020010db885a308d313198a2e037073488208ae82823aa0fbc914b16819237dcd8801d7e53f69e9719adecb3cc0e790c57e91ca4461c9548443b9a355c6010203c2040506a0c969a58f6f9095004c0177a6b47f451530cab38966a25cca5cb58f055542124e', - 'hex' + const bytes = hexToBytes( + '09b2428d83348d27cdf7064ad9024f526cebc19e4958f0fdad87c15eb598dd61d08423e0bf66b2069869e1724125f820d851c136684082774f870e614d95a2855d000f05d1648b2d5945470bc187c2d2216fbe870f43ed0909009882e176a46b0102f846d79020010db885a308d313198a2e037073488208ae82823aa0fbc914b16819237dcd8801d7e53f69e9719adecb3cc0e790c57e91ca4461c9548443b9a355c6010203c2040506a0c969a58f6f9095004c0177a6b47f451530cab38966a25cca5cb58f055542124e' ) - const msg = message.decode(buffer) + const msg = message.decode(bytes) t.same(msg.typename, 'pong') t.same(msg.publicKey, publicKey) @@ -51,11 +46,10 @@ test('pong packet with additional list elements and additional random data', (t) }) test('findnode packet with additional list elements and additional random data', (t) => { - const buffer = Buffer.from( - 'c7c44041b9f7c7e41934417ebac9a8e1a4c6298f74553f2fcfdcae6ed6fe53163eb3d2b52e39fe91831b8a927bf4fc222c3902202027e5e9eb812195f95d20061ef5cd31d502e47ecb61183f74a504fe04c51e73df81f25c4d506b26db4517490103f84eb840ca634cae0d49acb401d8a4c6b6fe8c55b70d115bf400769cc1400f3258cd31387574077f301b421bc84df7266c44e9e6d569fc56be00812904767bf5ccd1fc7f8443b9a35582999983999999280dc62cc8255c73471e0a61da0c89acdc0e035e260add7fc0c04ad9ebf3919644c91cb247affc82b69bd2ca235c71eab8e49737c937a2c396', - 'hex' + const bytes = hexToBytes( + 'c7c44041b9f7c7e41934417ebac9a8e1a4c6298f74553f2fcfdcae6ed6fe53163eb3d2b52e39fe91831b8a927bf4fc222c3902202027e5e9eb812195f95d20061ef5cd31d502e47ecb61183f74a504fe04c51e73df81f25c4d506b26db4517490103f84eb840ca634cae0d49acb401d8a4c6b6fe8c55b70d115bf400769cc1400f3258cd31387574077f301b421bc84df7266c44e9e6d569fc56be00812904767bf5ccd1fc7f8443b9a35582999983999999280dc62cc8255c73471e0a61da0c89acdc0e035e260add7fc0c04ad9ebf3919644c91cb247affc82b69bd2ca235c71eab8e49737c937a2c396' ) - const msg = message.decode(buffer) + const msg = message.decode(bytes) t.same(msg.typename, 'findneighbours') t.same(msg.publicKey, publicKey) @@ -64,11 +58,10 @@ test('findnode packet with additional list elements and additional random data', }) test('neighbours packet with additional list elements and additional random data', (t) => { - const buffer = Buffer.from( - 'c679fc8fe0b8b12f06577f2e802d34f6fa257e6137a995f6f4cbfc9ee50ed3710faf6e66f932c4c8d81d64343f429651328758b47d3dbc02c4042f0fff6946a50f4a49037a72bb550f3a7872363a83e1b9ee6469856c24eb4ef80b7535bcf99c0004f9015bf90150f84d846321163782115c82115db8403155e1427f85f10a5c9a7755877748041af1bcd8d474ec065eb33df57a97babf54bfd2103575fa829115d224c523596b401065a97f74010610fce76382c0bf32f84984010203040101b840312c55512422cf9b8a4097e9a6ad79402e87a15ae909a4bfefa22398f03d20951933beea1e4dfa6f968212385e829f04c2d314fc2d4e255e0d3bc08792b069dbf8599020010db83c4d001500000000abcdef12820d05820d05b84038643200b172dcfef857492156971f0e6aa2c538d8b74010f8e140811d53b98c765dd2d96126051913f44582e8c199ad7c6d6819e9a56483f637feaac9448aacf8599020010db885a308d313198a2e037073488203e78203e8b8408dcab8618c3253b558d459da53bd8fa68935a719aff8b811197101a4b2b47dd2d47295286fc00cc081bb542d760717d1bdd6bec2c37cd72eca367d6dd3b9df738443b9a355010203b525a138aa34383fec3d2719a0', - 'hex' + const bytes = hexToBytes( + 'c679fc8fe0b8b12f06577f2e802d34f6fa257e6137a995f6f4cbfc9ee50ed3710faf6e66f932c4c8d81d64343f429651328758b47d3dbc02c4042f0fff6946a50f4a49037a72bb550f3a7872363a83e1b9ee6469856c24eb4ef80b7535bcf99c0004f9015bf90150f84d846321163782115c82115db8403155e1427f85f10a5c9a7755877748041af1bcd8d474ec065eb33df57a97babf54bfd2103575fa829115d224c523596b401065a97f74010610fce76382c0bf32f84984010203040101b840312c55512422cf9b8a4097e9a6ad79402e87a15ae909a4bfefa22398f03d20951933beea1e4dfa6f968212385e829f04c2d314fc2d4e255e0d3bc08792b069dbf8599020010db83c4d001500000000abcdef12820d05820d05b84038643200b172dcfef857492156971f0e6aa2c538d8b74010f8e140811d53b98c765dd2d96126051913f44582e8c199ad7c6d6819e9a56483f637feaac9448aacf8599020010db885a308d313198a2e037073488203e78203e8b8408dcab8618c3253b558d459da53bd8fa68935a719aff8b811197101a4b2b47dd2d47295286fc00cc081bb542d760717d1bdd6bec2c37cd72eca367d6dd3b9df738443b9a355010203b525a138aa34383fec3d2719a0' ) - const msg = message.decode(buffer) + const msg = message.decode(bytes) t.same(msg.typename, 'neighbours') t.same(msg.publicKey, publicKey) diff --git a/packages/devp2p/test/enr.spec.ts b/packages/devp2p/test/enr.spec.ts index b17e40713b..c829579b24 100644 --- a/packages/devp2p/test/enr.spec.ts +++ b/packages/devp2p/test/enr.spec.ts @@ -1,3 +1,4 @@ +import { utf8ToBytes } from 'ethereum-cryptography/utils' import * as test from 'tape' import { ENR } from '../src/dns' @@ -107,7 +108,6 @@ test('ENR (branch): should error if DNS branch entry is mis-prefixed', (t) => { // ENR DNS entries test('ENR (enr): should convert an Ethereum Name Record string', (t) => { const { address, tcpPort, udpPort } = ENR.parseAndVerifyRecord(dns.enr) - t.equal(address, '40.113.111.135', 'returns correct address') t.equal(tcpPort, 30303, 'returns correct tcpPort') t.equal(udpPort, 30303, 'returns correct udpPort') @@ -125,7 +125,7 @@ test('ENR (enr): should convert non-padded Ethereum Name Record string', (t) => test('ENR (enr): should return correct multiaddr conversion codes for ipv6', (t) => { const expected = { ipCode: 41, tcpCode: 6, udpCode: 273 } - const protocolId = Buffer.from('v6') + const protocolId = utf8ToBytes('v6') const codes = ENR._getIpProtocolConversionCodes(protocolId) t.deepEqual(codes, expected, 'returns correct codes') @@ -145,7 +145,7 @@ test('ENR (enr): should error if record mis-prefixed', (t) => { }) test('ENR (enr): should error when converting to unrecognized ip protocol id', (t) => { - const protocolId = Buffer.from('v7') + const protocolId = utf8ToBytes('v7') try { ENR._getIpProtocolConversionCodes(protocolId) } catch (e: any) { diff --git a/packages/devp2p/test/integration/dpt-simulator.spec.ts b/packages/devp2p/test/integration/dpt-simulator.spec.ts index 30545fdbf7..8543d7a41c 100644 --- a/packages/devp2p/test/integration/dpt-simulator.spec.ts +++ b/packages/devp2p/test/integration/dpt-simulator.spec.ts @@ -130,7 +130,7 @@ test('DPT: simulate bootstrap', async (t) => { util.destroyDPTs(dpts) }) -test('DPT: simulate acquiring peers via DNS', async () => { +test('DPT: simulate acquiring peers via DNS', async (t) => { const dpts = util.getTestDPTsWithDns(1) const mockDns = { @@ -138,10 +138,11 @@ test('DPT: simulate acquiring peers via DNS', async () => { return [[testdata.dns.enr]] }, } - + dpts[0]._addPeerBatch = () => { + dpts[0].destroy() + t.pass('got peer from DNS') + t.end() + } dpts[0].dns.__setNativeDNSModuleResolve(mockDns) - dpts[0].refresh() - await util.delay(400) - - util.destroyDPTs(dpts) + await dpts[0].refresh() }) diff --git a/packages/devp2p/test/integration/eth-simulator.spec.ts b/packages/devp2p/test/integration/eth-simulator.spec.ts index 09e8d629a1..c65ea644db 100644 --- a/packages/devp2p/test/integration/eth-simulator.spec.ts +++ b/packages/devp2p/test/integration/eth-simulator.spec.ts @@ -1,4 +1,6 @@ import { Chain, Common, Hardfork } from '@ethereumjs/common' +import { intToBytes } from '@ethereumjs/util' +import { hexToBytes } from 'ethereum-cryptography/utils' import * as test from 'tape' import * as devp2p from '../../src' @@ -7,15 +9,12 @@ import { ETH } from '../../src' import * as util from './util' const GENESIS_TD = 17179869184 -const GENESIS_HASH = Buffer.from( - 'd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3', - 'hex' -) +const GENESIS_HASH = hexToBytes('d4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3') const capabilities = [devp2p.ETH.eth63, devp2p.ETH.eth62] const status = { - td: devp2p.int2buffer(GENESIS_TD), + td: intToBytes(GENESIS_TD), bestHash: GENESIS_HASH, genesisHash: GENESIS_HASH, } @@ -55,7 +54,7 @@ test('ETH: send status message (Genesis block mismatch)', (t) => { const opts: any = {} opts.status0 = Object.assign({}, status) const status1 = Object.assign({}, status) - status1['genesisHash'] = Buffer.alloc(32) + status1['genesisHash'] = new Uint8Array(32) opts.status1 = status1 opts.onPeerError0 = function (err: Error, rlpxs: any) { const msg = @@ -116,7 +115,7 @@ test('ETH -> Eth64 -> sendStatus(): should throw on non-matching latest block pr const cap = [devp2p.ETH.eth65] const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Byzantium }) const status0: any = Object.assign({}, status) - status0['latestBlock'] = 100000 // lower than Byzantium fork block 4370000 + status0['latestBlock'] = intToBytes(100000) // lower than Byzantium fork block 4370000 const rlpxs = util.initTwoPeerRLPXSetup(null, cap, common) rlpxs[0].on('peer:added', function (peer: any) { @@ -145,7 +144,7 @@ test('ETH -> Eth64 -> ForkId validation 1a)', (t) => { const status0: any = Object.assign({}, status) // Take a latest block > next mainnet fork block (constantinople) // to trigger validation condition - status0['latestBlock'] = 9069000 + status0['latestBlock'] = intToBytes(9069000) opts.status0 = status0 opts.status1 = Object.assign({}, status) opts.onPeerError0 = function (err: Error, rlpxs: any) { diff --git a/packages/devp2p/test/integration/les-simulator.spec.ts b/packages/devp2p/test/integration/les-simulator.spec.ts index 7ebeeb9da3..6190ad4a76 100644 --- a/packages/devp2p/test/integration/les-simulator.spec.ts +++ b/packages/devp2p/test/integration/les-simulator.spec.ts @@ -1,4 +1,6 @@ import { Chain, Common, Hardfork } from '@ethereumjs/common' +import { intToBytes } from '@ethereumjs/util' +import { hexToBytes } from 'ethereum-cryptography/utils' import * as test from 'tape' import * as devp2p from '../../src' @@ -6,17 +8,14 @@ import * as devp2p from '../../src' import * as util from './util' const GENESIS_TD = 17179869184 -const GENESIS_HASH = Buffer.from( - 'd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3', - 'hex' -) +const GENESIS_HASH = hexToBytes('d4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3') const capabilities = [devp2p.LES.les4] const status = { - headTd: devp2p.int2buffer(GENESIS_TD), // total difficulty in genesis block + headTd: intToBytes(GENESIS_TD), // total difficulty in genesis block headHash: GENESIS_HASH, - headNum: devp2p.int2buffer(0), + headNum: intToBytes(0), genesisHash: GENESIS_HASH, } @@ -69,7 +68,7 @@ test('ETH: send status message (Genesis block mismatch)', (t) => { const opts: any = {} opts.status0 = Object.assign({}, status) const status1 = Object.assign({}, status) - status1['genesisHash'] = Buffer.alloc(32) + status1['genesisHash'] = new Uint8Array(32) opts.status1 = status1 opts.onPeerError0 = function (err: Error, rlpxs: any) { const msg = diff --git a/packages/devp2p/test/integration/rlpx-simulator.spec.ts b/packages/devp2p/test/integration/rlpx-simulator.spec.ts index 078772a3d7..4e6f1c70eb 100644 --- a/packages/devp2p/test/integration/rlpx-simulator.spec.ts +++ b/packages/devp2p/test/integration/rlpx-simulator.spec.ts @@ -1,3 +1,4 @@ +import { hexToBytes } from 'ethereum-cryptography/utils' import * as test from 'tape' import { DISCONNECT_REASONS } from '../../src/rlpx/peer' @@ -22,7 +23,7 @@ test('RLPX: ban node with missing tcp port', (t) => { rlpxs[0].on('peer:added', async () => { const peer = { - id: Buffer.from('abcd', 'hex'), + id: hexToBytes('abcd'), address: '127.0.0.1', udpPort: 30308, tcpPort: null, diff --git a/packages/devp2p/test/integration/util.ts b/packages/devp2p/test/integration/util.ts index 5d4ea3b86b..4c11feec3f 100644 --- a/packages/devp2p/test/integration/util.ts +++ b/packages/devp2p/test/integration/util.ts @@ -185,7 +185,7 @@ export function twoPeerMsgExchange2( clientId: 'fakePeer', capabilities: [ETH.eth66], port: 30303, - id: Buffer.alloc(12), + id: new Uint8Array(12), } // Set peer's devp2p protocol version to 4 protocol._peer._hello = v4Hello diff --git a/packages/devp2p/test/rlpx-ecies.spec.ts b/packages/devp2p/test/rlpx-ecies.spec.ts index 5ba45fd6f5..3539d23852 100644 --- a/packages/devp2p/test/rlpx-ecies.spec.ts +++ b/packages/devp2p/test/rlpx-ecies.spec.ts @@ -1,5 +1,6 @@ -import { randomBytes } from 'crypto' +import { getRandomBytesSync } from 'ethereum-cryptography/random' import { publicKeyCreate } from 'ethereum-cryptography/secp256k1-compat' +import { hexToBytes, utf8ToBytes } from 'ethereum-cryptography/utils' import * as test from 'tape' import { ECIES } from '../src/rlpx/ecies' @@ -14,8 +15,8 @@ declare module 'tape' { context: { a: ECIES b: ECIES - h0?: { auth: Buffer; ack: Buffer } - h1?: { auth: Buffer; ack: Buffer } + h0?: { auth: Uint8Array; ack: Uint8Array } + h1?: { auth: Uint8Array; ack: Uint8Array } } } } @@ -24,8 +25,8 @@ function randomBefore(fn: Function) { return (t: Test) => { const privateKey1 = util.genPrivateKey() const privateKey2 = util.genPrivateKey() - const publicKey1 = Buffer.from(publicKeyCreate(privateKey1, false)) - const publicKey2 = Buffer.from(publicKeyCreate(privateKey2, false)) + const publicKey1 = publicKeyCreate(privateKey1, false) + const publicKey2 = publicKeyCreate(privateKey2, false) t.context = { a: new ECIES(privateKey1, util.pk2id(publicKey1), util.pk2id(publicKey2)), b: new ECIES(privateKey2, util.pk2id(publicKey2), util.pk2id(publicKey1)), @@ -38,22 +39,22 @@ function randomBefore(fn: Function) { function testdataBefore(fn: Function) { return (t: Test) => { const v = testdata.eip8Values - const keyA = Buffer.from(v.keyA, 'hex') - const keyB = Buffer.from(v.keyB, 'hex') - const pubA = Buffer.from(v.pubA, 'hex') - const pubB = Buffer.from(v.pubB, 'hex') + const keyA = hexToBytes(v.keyA) + const keyB = hexToBytes(v.keyB) + const pubA = hexToBytes(v.pubA) + const pubB = hexToBytes(v.pubB) const h = testdata.eip8Handshakes t.context = { a: new ECIES(keyA, util.pk2id(pubA), util.pk2id(pubB)), b: new ECIES(keyB, util.pk2id(pubB), util.pk2id(pubA)), h0: { - auth: Buffer.from(h[0].auth.join(''), 'hex'), - ack: Buffer.from(h[0].ack.join(''), 'hex'), + auth: hexToBytes(h[0].auth.join('')), + ack: hexToBytes(h[0].ack.join('')), }, h1: { - auth: Buffer.from(h[1].auth.join(''), 'hex'), - ack: Buffer.from(h[1].ack.join(''), 'hex'), + auth: hexToBytes(h[1].auth.join('')), + ack: hexToBytes(h[1].ack.join('')), }, } fn(t) @@ -63,9 +64,9 @@ function testdataBefore(fn: Function) { test( 'Random: message encryption', randomBefore((t: Test) => { - const message = Buffer.from('The Magic Words are Squeamish Ossifrage') + const message = utf8ToBytes('The Magic Words are Squeamish Ossifrage') const encrypted = t.context.a._encryptMessage(message) - const decrypted = t.context.b._decryptMessage(encrypted as Buffer) + const decrypted = t.context.b._decryptMessage(encrypted as Uint8Array) t.same(message, decrypted, 'encryptMessage -> decryptMessage should lead to same') t.end() }) @@ -77,21 +78,21 @@ test( t.doesNotThrow(() => { const auth = t.context.a.createAuthNonEIP8() t.context.b._gotEIP8Auth = false - t.context.b.parseAuthPlain(auth as Buffer) + t.context.b.parseAuthPlain(auth as Uint8Array) }, 'should not throw on auth creation/parsing') t.doesNotThrow(() => { t.context.b._gotEIP8Ack = false const ack = t.context.b.createAckOld() - t.context.a.parseAckPlain(ack as Buffer) + t.context.a.parseAckPlain(ack as Uint8Array) }, 'should not throw on ack creation/parsing') - const body = randomBytes(600) + const body = getRandomBytesSync(600) - const header = t.context.b.parseHeader(t.context.a.createHeader(body.length) as Buffer) + const header = t.context.b.parseHeader(t.context.a.createHeader(body.length) as Uint8Array) t.same(header, body.length, 'createHeader -> parseHeader should lead to same') - const parsedBody = t.context.b.parseBody(t.context.a.createBody(body) as Buffer) + const parsedBody = t.context.b.parseBody(t.context.a.createBody(body) as Uint8Array) t.same(parsedBody, body, 'createBody -> parseBody should lead to same') t.end() @@ -104,13 +105,13 @@ test( t.doesNotThrow(() => { const auth = t.context.a.createAuthEIP8() t.context.b._gotEIP8Auth = true - t.context.b.parseAuthEIP8(auth as Buffer) + t.context.b.parseAuthEIP8(auth as Uint8Array) }, 'should not throw on auth creation/parsing') t.doesNotThrow(() => { const ack = t.context.b.createAckEIP8() t.context.a._gotEIP8Ack = true - t.context.a.parseAckEIP8(ack as Buffer) + t.context.a.parseAckEIP8(ack as Uint8Array) }, 'should not throw on ack creation/parsing') t.end() @@ -122,13 +123,13 @@ test( testdataBefore((t: Test) => { t.doesNotThrow(() => { t.context.b._gotEIP8Auth = false - t.context.b.parseAuthPlain(t.context.h0?.auth as Buffer) + t.context.b.parseAuthPlain(t.context.h0?.auth as Uint8Array) t.context.a._initMsg = t.context.h0?.auth }, 'should not throw on auth parsing') t.doesNotThrow(() => { t.context.a._gotEIP8Ack = false - t.context.a.parseAckPlain(t.context.h0?.ack as Buffer) + t.context.a.parseAckPlain(t.context.h0?.ack as Uint8Array) }, 'should not throw on ack parsing') t.end() @@ -140,12 +141,12 @@ test( testdataBefore((t: Test) => { t.doesNotThrow(() => { t.context.b._gotEIP8Auth = true - t.context.b.parseAuthEIP8(t.context.h1?.auth as Buffer) + t.context.b.parseAuthEIP8(t.context.h1?.auth as Uint8Array) t.context.a._initMsg = t.context.h1?.auth }, 'should not throw on auth parsing') t.doesNotThrow(() => { t.context.a._gotEIP8Ack = true - t.context.a.parseAckEIP8(t.context.h1?.ack as Buffer) + t.context.a.parseAckEIP8(t.context.h1?.ack as Uint8Array) }, 'should not throw on ack parsing') t.end() diff --git a/packages/devp2p/test/rlpx-mac.spec.ts b/packages/devp2p/test/rlpx-mac.spec.ts index a2a769bb0d..d35e8fa124 100644 --- a/packages/devp2p/test/rlpx-mac.spec.ts +++ b/packages/devp2p/test/rlpx-mac.spec.ts @@ -1,36 +1,34 @@ +import { bytesToHex, hexToBytes } from 'ethereum-cryptography/utils' import * as test from 'tape' import { MAC } from '../src/rlpx/mac' -const secret = Buffer.from( - '4caf4671e713d083128973de159d02688dc86f51535a80178264631e193ed2ea', - 'hex' -) +const secret = hexToBytes('4caf4671e713d083128973de159d02688dc86f51535a80178264631e193ed2ea') test('digest should work on empty data', (t) => { const mac = new MAC(secret) - t.equal(mac.digest().toString('hex'), 'c5d2460186f7233c927e7db2dcc703c0') + t.equal(bytesToHex(mac.digest()), 'c5d2460186f7233c927e7db2dcc703c0') t.end() }) test('#update', (t) => { const mac = new MAC(secret) mac.update('test') - t.equal(mac.digest().toString('hex'), '9c22ff5f21f0b81b113e63f7db6da94f') + t.equal(bytesToHex(mac.digest()), '9c22ff5f21f0b81b113e63f7db6da94f') t.end() }) test('#updateHeader', (t) => { const mac = new MAC(secret) mac.updateHeader('this is a header data struct') - t.equal(mac.digest().toString('hex'), '52235ed491a4c9224d94788762ead6a6') + t.equal(bytesToHex(mac.digest()), '52235ed491a4c9224d94788762ead6a6') t.end() }) test('#updateBody', (t) => { const mac = new MAC(secret) mac.updateBody('this is a body data struct') - t.equal(mac.digest().toString('hex'), '134a755450b1ed9d3ff90ef5dcecdd7d') + t.equal(bytesToHex(mac.digest()), '134a755450b1ed9d3ff90ef5dcecdd7d') t.end() }) @@ -38,6 +36,6 @@ test('#updateHeader and #updateBody', (t) => { const mac = new MAC(secret) mac.updateHeader('this is a header data struct') mac.updateBody('this is a body data struct') - t.equal(mac.digest().toString('hex'), '5d98967578ec8edbb45e1d75992f394c') + t.equal(bytesToHex(mac.digest()), '5d98967578ec8edbb45e1d75992f394c') t.end() }) diff --git a/packages/ethash/examples/example.ts b/packages/ethash/examples/example.ts index 441a6d6923..ad1aa738fe 100644 --- a/packages/ethash/examples/example.ts +++ b/packages/ethash/examples/example.ts @@ -1,10 +1,12 @@ +import { bytesToHex } from '@ethereumjs/util' +import { hexToBytes } from 'ethereum-cryptography/utils' import { Ethash } from '../src' const ethash = new Ethash() // make the 1000 cache items with a seed of 0 * 32 -ethash.mkcache(1000, Buffer.alloc(32).fill(0)) +ethash.mkcache(1000, new Uint8Array(32).fill(0)) -const result = ethash.run(Buffer.from('test'), Buffer.from([0]), 1000) +const result = ethash.run(hexToBytes('test'), Uint8Array.from([0]), 1000) -console.log(result.hash.toString('hex')) +console.log(bytesToHex(result.hash)) diff --git a/packages/ethash/examples/rawExample.ts b/packages/ethash/examples/rawExample.ts index 8e198482b5..213312c399 100644 --- a/packages/ethash/examples/rawExample.ts +++ b/packages/ethash/examples/rawExample.ts @@ -1,28 +1,27 @@ -import Ethash, { EthashCacheDB } from '../src' +import { Ethash } from '../src' import { MemoryLevel } from 'memory-level' +import { bytesToHex } from '@ethereumjs/util' +import { hexToBytes } from 'ethereum-cryptography/utils' const ethash = new Ethash(new MemoryLevel()) const verifySubmit = async ( ethash: Ethash, number: number, - headerHash: Buffer, - nonce: Buffer -): Promise => { + headerHash: Uint8Array, + nonce: Uint8Array +): Promise => { console.log('Verifying number: ', number) await ethash.loadEpoc(BigInt(number)) console.log('EPOC set') - console.log('Seed: ', ethash.seed!.toString('hex')) + console.log('Seed: ', bytesToHex(ethash.seed!)) const a = ethash.run(headerHash, nonce) return a.hash } -const headerHash = Buffer.from( - '0e2887aa1a0668bf8254d1a6ae518927de99e3e5d7f30fd1f16096e2608fe05e', - 'hex' -) -const nonce = Buffer.from('e360b6170c229d15', 'hex') +const headerHash = hexToBytes('0e2887aa1a0668bf8254d1a6ae518927de99e3e5d7f30fd1f16096e2608fe05e') +const nonce = hexToBytes('e360b6170c229d15') verifySubmit(ethash, 35414, headerHash, nonce).then((result) => { - console.log('Result: ', result.toString('hex')) + console.log('Result: ', bytesToHex(result)) }) diff --git a/packages/ethash/package.json b/packages/ethash/package.json index ade619568c..17f11016b3 100644 --- a/packages/ethash/package.json +++ b/packages/ethash/package.json @@ -32,6 +32,7 @@ "lint:diff": "../../config/cli/lint-diff.sh", "lint:fix": "../../config/cli/lint-fix.sh", "prepublishOnly": "../../config/cli/prepublish.sh", + "tape": "tape -r ts-node/register", "test": "tape -r ts-node/register test/*.spec.ts", "tsc": "../../config/cli/ts-compile.sh" }, diff --git a/packages/ethash/src/index.ts b/packages/ethash/src/index.ts index 6fabc2d65d..88c7885214 100644 --- a/packages/ethash/src/index.ts +++ b/packages/ethash/src/index.ts @@ -2,18 +2,19 @@ import { Block, BlockHeader } from '@ethereumjs/block' import { RLP } from '@ethereumjs/rlp' import { TWO_POW256, - bigIntToBuffer, - bufArrToArr, - bufferToBigInt, + bigIntToBytes, + bytesToBigInt, + concatBytes, + equalsBytes, setLengthLeft, zeros, } from '@ethereumjs/util' import { keccak256, keccak512 } from 'ethereum-cryptography/keccak' import { - bufReverse, + bytesReverse, fnv, - fnvBuffer, + fnvBytes, getCacheSize, getEpoc, getFullSize, @@ -24,9 +25,9 @@ import { import type { BlockData, HeaderData } from '@ethereumjs/block' import type { AbstractLevel } from 'abstract-level' -function xor(a: Buffer, b: Buffer) { +function xor(a: Uint8Array, b: Uint8Array) { const len = Math.max(a.length, b.length) - const res = Buffer.alloc(len) + const res = new Uint8Array(len) for (let i = 0; i < len; i++) { res[i] = a[i] ^ b[i] } @@ -34,8 +35,8 @@ function xor(a: Buffer, b: Buffer) { } export type Solution = { - mixHash: Buffer - nonce: Buffer + mixHash: Uint8Array + nonce: Uint8Array } export class Miner { @@ -46,7 +47,7 @@ export class Miner { public solution?: Solution private currentNonce: bigint - private headerHash?: Buffer + private headerHash?: Uint8Array private stopMining: boolean /** @@ -122,10 +123,10 @@ export class Miner { // Without this, for high-difficulty blocks JS never jumps out of the Promise const solution: Solution | null = await new Promise((resolve) => { setTimeout(() => { - const nonce = setLengthLeft(bigIntToBuffer(this.currentNonce), 8) + const nonce = setLengthLeft(bigIntToBytes(this.currentNonce), 8) const a = this.ethash.run(headerHash, nonce) - const result = bufferToBigInt(a.hash) + const result = bytesToBigInt(a.hash) if (TWO_POW256 / difficulty > result) { const solution: Solution = { @@ -152,24 +153,24 @@ export class Miner { } export type EthashCacheDB = AbstractLevel< - string | Buffer | Uint8Array, - string | Buffer, + string | Uint8Array, + string | Uint8Array, { - cache: Buffer[] + cache: Uint8Array[] fullSize: number cacheSize: number - seed: Buffer + seed: Uint8Array } > export class Ethash { dbOpts: Object cacheDB?: EthashCacheDB - cache: Buffer[] + cache: Uint8Array[] epoc?: number fullSize?: number cacheSize?: number - seed?: Buffer + seed?: Uint8Array constructor(cacheDB?: EthashCacheDB) { this.dbOpts = { @@ -179,20 +180,19 @@ export class Ethash { this.cache = [] } - mkcache(cacheSize: number, seed: Buffer) { - // console.log(`generating cache\nsize: ${cacheSize}\nseed: ${seed.toString('hex')}`) + mkcache(cacheSize: number, seed: Uint8Array) { const n = Math.floor(cacheSize / params.HASH_BYTES) - const o = [Buffer.from(keccak512(seed))] + const o = [keccak512(seed)] let i for (i = 1; i < n; i++) { - o.push(Buffer.from(keccak512(o[o.length - 1]))) + o.push(keccak512(o[o.length - 1])) } for (let _ = 0; _ < params.CACHE_ROUNDS; _++) { for (i = 0; i < n; i++) { - const v = o[i].readUInt32LE(0) % n - o[i] = Buffer.from(keccak512(xor(o[(i - 1 + n) % n], o[v]))) + const v = new DataView(o[i].buffer).getUint32(0, true) % n + o[i] = keccak512(xor(o[(i - 1 + n) % n], o[v])) } } @@ -200,20 +200,21 @@ export class Ethash { return this.cache } - calcDatasetItem(i: number): Buffer { + calcDatasetItem(i: number): Uint8Array { const n = this.cache.length const r = Math.floor(params.HASH_BYTES / params.WORD_BYTES) - let mix = Buffer.from(this.cache[i % n]) - mix.writeInt32LE(mix.readUInt32LE(0) ^ i, 0) - mix = Buffer.from(keccak512(mix)) + let mix = new Uint8Array(this.cache[i % n]) + const mixView = new DataView(mix.buffer) + mixView.setUint32(0, mixView.getUint32(0, true) ^ i, true) + mix = keccak512(mix) for (let j = 0; j < params.DATASET_PARENTS; j++) { - const cacheIndex = fnv(i ^ j, mix.readUInt32LE((j % r) * 4)) - mix = fnvBuffer(mix, this.cache[cacheIndex % n]) + const cacheIndex = fnv(i ^ j, new DataView(mix.buffer).getUint32((j % r) * 4, true)) + mix = fnvBytes(mix, this.cache[cacheIndex % n]) } - return Buffer.from(keccak512(mix)) + return keccak512(mix) } - run(val: Buffer, nonce: Buffer, fullSize?: number) { + run(val: Uint8Array, nonce: Uint8Array, fullSize?: number) { if (fullSize === undefined) { if (this.fullSize === undefined) { throw new Error('fullSize needed') @@ -223,42 +224,59 @@ export class Ethash { } const n = Math.floor(fullSize / params.HASH_BYTES) const w = Math.floor(params.MIX_BYTES / params.WORD_BYTES) - const s = Buffer.from(keccak512(Buffer.concat([val, bufReverse(nonce)]))) + const s = keccak512(concatBytes(val, bytesReverse(nonce))) const mixhashes = Math.floor(params.MIX_BYTES / params.HASH_BYTES) - let mix = Buffer.concat(Array(mixhashes).fill(s)) + let mix = concatBytes(...Array(mixhashes).fill(s)) let i for (i = 0; i < params.ACCESSES; i++) { const p = - (fnv(i ^ s.readUInt32LE(0), mix.readUInt32LE((i % w) * 4)) % Math.floor(n / mixhashes)) * + (fnv( + i ^ new DataView(s.buffer).getUint32(0, true), + new DataView(mix.buffer).getUint32((i % w) * 4, true) + ) % + Math.floor(n / mixhashes)) * mixhashes - const newdata = [] + const newdata: Uint8Array[] = [] for (let j = 0; j < mixhashes; j++) { newdata.push(this.calcDatasetItem(p + j)) } - mix = fnvBuffer(mix, Buffer.concat(newdata)) + mix = fnvBytes(mix, concatBytes(...newdata)) } - const cmix = Buffer.alloc(mix.length / 4) + const cmix = new Uint8Array(mix.length / 4) + const cmixView = new DataView(cmix.buffer) + const mixView = new DataView(mix.buffer) for (i = 0; i < mix.length / 4; i = i + 4) { - const a = fnv(mix.readUInt32LE(i * 4), mix.readUInt32LE((i + 1) * 4)) - const b = fnv(a, mix.readUInt32LE((i + 2) * 4)) - const c = fnv(b, mix.readUInt32LE((i + 3) * 4)) - cmix.writeUInt32LE(c, i) + const a = fnv(mixView.getUint32(i * 4, true), mixView.getUint32((i + 1) * 4, true)) + const b = fnv(a, mixView.getUint32((i + 2) * 4, true)) + const c = fnv(b, mixView.getUint32((i + 3) * 4, true)) + cmixView.setUint32(i, c, true) } return { mix: cmix, - hash: Buffer.from(keccak256(Buffer.concat([s, cmix]))), + hash: keccak256(concatBytes(s, cmix)), } } cacheHash() { - return Buffer.from(keccak256(Buffer.concat(this.cache))) + // Concatenate all the cache bytes together + // We can't use `concatBytes` because calling `concatBytes(...this.cache)` results + // in a `Max call stack size exceeded` error due to the spread operator pushing all + // of the array elements onto the stack and the ethash cache can be quite large + const length = this.cache.reduce((a, arr) => a + arr.length, 0) + const result = new Uint8Array(length) + for (let i = 0, pad = 0; i < this.cache.length; i++) { + const arr = this.cache[i] + result.set(arr, pad) + pad += arr.length + } + return keccak256(result) } - headerHash(rawHeader: Buffer[]) { - return Buffer.from(keccak256(RLP.encode(bufArrToArr(rawHeader.slice(0, -2))))) + headerHash(rawHeader: Uint8Array[]) { + return keccak256(RLP.encode(rawHeader.slice(0, -2))) } /** @@ -278,7 +296,7 @@ export class Ethash { } // gives the seed the first epoc found - const findLastSeed = async (epoc: number): Promise<[Buffer, number]> => { + const findLastSeed = async (epoc: number): Promise<[Uint8Array, number]> => { if (epoc === 0) { return [zeros(32), 0] } @@ -325,12 +343,12 @@ export class Ethash { this.dbOpts ) } else { - this.cache = data.cache.map((a: Buffer) => { - return Buffer.from(a) + this.cache = data.cache.map((a: Uint8Array) => { + return Uint8Array.from(a) }) this.cacheSize = data.cacheSize this.fullSize = data.fullSize - this.seed = Buffer.from(data.seed) + this.seed = Uint8Array.from(data.seed) } } @@ -350,9 +368,8 @@ export class Ethash { await this.loadEpoc(number) const a = this.run(headerHash, nonce) - const result = bufferToBigInt(a.hash) - - return a.mix.equals(mixHash) && TWO_POW256 / difficulty > result + const result = bytesToBigInt(a.hash) + return equalsBytes(a.mix, mixHash) && TWO_POW256 / difficulty > result } async verifyPOW(block: Block) { diff --git a/packages/ethash/src/util.ts b/packages/ethash/src/util.ts index f4247cc28e..1804780c9d 100644 --- a/packages/ethash/src/util.ts +++ b/packages/ethash/src/util.ts @@ -44,13 +44,13 @@ export function getEpoc(blockNumber: bigint) { * Generates a seed give the end epoc and optional the beginning epoc and the * beginning epoc seed * @method getSeed - * @param seed Buffer + * @param seed Uint8Array * @param begin Number * @param end Number */ -export function getSeed(seed: Buffer, begin: number, end: number) { +export function getSeed(seed: Uint8Array, begin: number, end: number) { for (let i = begin; i < end; i++) { - seed = Buffer.from(keccak256(seed)) + seed = keccak256(seed) } return seed } @@ -59,17 +59,22 @@ export function fnv(x: number, y: number) { return ((((x * 0x01000000) | 0) + ((x * 0x193) | 0)) ^ y) >>> 0 } -export function fnvBuffer(a: Buffer, b: Buffer) { - const r = Buffer.alloc(a.length) +export function fnvBytes(a: Uint8Array, b: Uint8Array) { + const r = new Uint8Array(a.length) + const rView = new DataView(r.buffer) for (let i = 0; i < a.length; i = i + 4) { - r.writeUInt32LE(fnv(a.readUInt32LE(i), b.readUInt32LE(i)), i) + rView.setUint32( + i, + fnv(new DataView(a.buffer).getUint32(i, true), new DataView(b.buffer).getUint32(i, true)), + true + ) } return r } -export function bufReverse(a: Buffer) { +export function bytesReverse(a: Uint8Array) { const length = a.length - const b = Buffer.alloc(length) + const b = new Uint8Array(length) for (let i = 0; i < length; i++) { b[i] = a[length - i - 1] } diff --git a/packages/ethash/test/block.spec.ts b/packages/ethash/test/block.spec.ts index bdcc973518..11aa520e7a 100644 --- a/packages/ethash/test/block.spec.ts +++ b/packages/ethash/test/block.spec.ts @@ -1,13 +1,14 @@ import { Block } from '@ethereumjs/block' import { Chain, Common, Hardfork } from '@ethereumjs/common' import { RLP } from '@ethereumjs/rlp' -import { arrToBufArr, toBuffer } from '@ethereumjs/util' +import { toBytes } from '@ethereumjs/util' +import { hexToBytes } from 'ethereum-cryptography/utils' import { MemoryLevel } from 'memory-level' import * as tape from 'tape' import { Ethash } from '../src' -import type { BlockBuffer } from '@ethereumjs/block' +import type { BlockBytes } from '@ethereumjs/block' const cacheDB = new MemoryLevel() @@ -22,21 +23,21 @@ tape('Verify POW for valid and invalid blocks', async function (t) { const genesisResult = await e.verifyPOW(genesis) t.ok(genesisResult, 'genesis block should be valid') - const validRlp = Buffer.from(validBlockRlp, 'hex') + const validRlp = hexToBytes(validBlockRlp) const validBlock = Block.fromRLPSerializedBlock(validRlp, { common }) const validBlockResult = await e.verifyPOW(validBlock) t.ok(validBlockResult, 'should be valid') - const invalidRlp = Buffer.from(invalidBlockRlp, 'hex') + const invalidRlp = hexToBytes(invalidBlockRlp) // Put correct amount of extraData in block extraData field so block can be deserialized - const values = arrToBufArr(RLP.decode(Uint8Array.from(invalidRlp))) as BlockBuffer - values[0][12] = Buffer.alloc(32) + const values = RLP.decode(Uint8Array.from(invalidRlp)) as BlockBytes + values[0][12] = new Uint8Array(32) const invalidBlock = Block.fromValuesArray(values, { common }) const invalidBlockResult = await e.verifyPOW(invalidBlock) t.ok(!invalidBlockResult, 'should be invalid') const testData = require('./block_tests_data.json') - const blockRlp = toBuffer(testData.blocks[0].rlp) + const blockRlp = toBytes(testData.blocks[0].rlp) const block = Block.fromRLPSerializedBlock(blockRlp, { common }) const uncleBlockResult = await e.verifyPOW(block) t.ok(uncleBlockResult, 'should be valid') diff --git a/packages/ethash/test/ethash.spec.ts b/packages/ethash/test/ethash.spec.ts index d38e7053e7..c72b7b34fe 100644 --- a/packages/ethash/test/ethash.spec.ts +++ b/packages/ethash/test/ethash.spec.ts @@ -1,5 +1,7 @@ import { BlockHeader } from '@ethereumjs/block' import { Chain, Common, Hardfork } from '@ethereumjs/common' +import { bytesToHex } from '@ethereumjs/util' +import { hexToBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' import { Ethash } from '../src' @@ -14,20 +16,20 @@ const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Istanbul }) tape('POW tests', async function (t) { for (const key of tests) { const test = powTests[key] - const header = BlockHeader.fromRLPSerializedHeader(Buffer.from(test.header, 'hex'), { common }) + const header = BlockHeader.fromRLPSerializedHeader(hexToBytes(test.header), { common }) const headerHash = ethash.headerHash(header.raw()) - t.equal(headerHash.toString('hex'), test.header_hash, 'generate header hash') + t.equal(bytesToHex(headerHash), test.header_hash, 'generate header hash') const epoc = getEpoc(header.number) t.equal(await getCacheSize(epoc), test.cache_size, 'generate cache size') t.equal(await getFullSize(epoc), test.full_size, 'generate full cache size') - ethash.mkcache(test.cache_size, Buffer.from(test.seed, 'hex')) - t.equal(ethash.cacheHash().toString('hex'), test.cache_hash, 'generate cache') + ethash.mkcache(test.cache_size, hexToBytes(test.seed)) + t.equal(bytesToHex(ethash.cacheHash()), test.cache_hash, 'generate cache') - const r = ethash.run(headerHash, Buffer.from(test.nonce, 'hex'), test.full_size) - t.equal(r.hash.toString('hex'), test.result, 'generate result') - t.equal(r.mix.toString('hex'), test.mixHash, 'generate mix hash') + const r = ethash.run(headerHash, hexToBytes(test.nonce), test.full_size) + t.equal(bytesToHex(r.hash), test.result, 'generate result') + t.equal(bytesToHex(r.mix), test.mixHash, 'generate mix hash') } }) diff --git a/packages/ethash/test/miner.spec.ts b/packages/ethash/test/miner.spec.ts index 4327e54043..5bd1e035cc 100644 --- a/packages/ethash/test/miner.spec.ts +++ b/packages/ethash/test/miner.spec.ts @@ -7,11 +7,10 @@ import { Ethash } from '../src' import type { BlockHeader } from '@ethereumjs/block' -const cacheDB = new MemoryLevel() const common = new Common({ chain: Chain.Ropsten, hardfork: Hardfork.Petersburg }) tape('Check if miner works as expected', async function (t) { - const e = new Ethash(cacheDB as any) + const e = new Ethash(new MemoryLevel()) const block = Block.fromBlockData( { @@ -55,7 +54,7 @@ tape('Check if miner works as expected', async function (t) { }) tape('Check if it is possible to mine Blocks and BlockHeaders', async function (t) { - const e = new Ethash(cacheDB as any) + const e = new Ethash(new MemoryLevel()) const block = Block.fromBlockData( { @@ -66,7 +65,6 @@ tape('Check if it is possible to mine Blocks and BlockHeaders', async function ( }, { common } ) - const miner = e.getMiner(block.header) const solution = await miner.mine(-1) @@ -84,7 +82,7 @@ tape('Check if it is possible to mine Blocks and BlockHeaders', async function ( }) tape('Check if it is possible to stop the miner', async function (t) { - const e = new Ethash(cacheDB as any) + const e = new Ethash(new MemoryLevel()) const block = Block.fromBlockData( { @@ -95,7 +93,6 @@ tape('Check if it is possible to stop the miner', async function (t) { }, { common } ) - const miner = e.getMiner(block.header) setTimeout(function () { miner.stop() @@ -107,7 +104,7 @@ tape('Check if it is possible to stop the miner', async function (t) { }) tape('Check if it is possible to stop the miner', async function (t) { - const e = new Ethash(cacheDB as any) + const e = new Ethash(new MemoryLevel()) const block: any = {} @@ -119,7 +116,7 @@ tape('Check if it is possible to stop the miner', async function (t) { }) tape('Should keep common when mining blocks or headers', async function (t) { - const e = new Ethash(cacheDB as any) + const e = new Ethash(new MemoryLevel()) const block = Block.fromBlockData( { diff --git a/packages/evm/examples/decode-opcodes.ts b/packages/evm/examples/decode-opcodes.ts index 2e6ae419d3..d2cc372dd6 100644 --- a/packages/evm/examples/decode-opcodes.ts +++ b/packages/evm/examples/decode-opcodes.ts @@ -3,6 +3,7 @@ // 1. Takes binary EVM code and decodes it into opcodes import { Chain, Common, Hardfork } from '@ethereumjs/common' +import { bytesToHex, hexToBytes } from 'ethereum-cryptography/utils' import { getOpcodesForHF } from '../src/opcodes' const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Istanbul }) @@ -11,10 +12,10 @@ const opcodes = getOpcodesForHF(common).opcodes const data = '6107608061000e6000396000f30060003560e060020a90048063141961bc1461006e57806319ac74bd146100cf578063278ecde1146100e75780632c0f7b6f146100f8578063a87430ba1461010a578063ac273aa21461011f578063c06f4c1d14610133578063c1cbbca714610159578063e11523431461016a57005b610079600435610183565b8b6000528a60205289600160a060020a031660405288600160a060020a0316606052876080528660a0528560c0528460e05283610100528261012052816101405280600160a060020a0316610160526101806000f35b6100dd6004356024356106e8565b8060005260206000f35b6100f2600435610454565b60006000f35b61010061017c565b8060005260206000f35b6101156004356101da565b8060005260206000f35b61012d600435602435610729565b60006000f35b61015360043560243560443560643560843560a43560c43560e4356101ee565b60006000f35b610164600435610302565b60006000f35b6101756004356105dd565b60006000f35b5b60005481565b5b6000526001602052604060002080549080600101549080600201549080600301549080600401549080600501549080600601549080600701549080600801549080600901549080600c01549080600d015490508c565b5b600052600260205260406000208054905081565b600060006000600060008811801561020557504287115b61020e576102f4565b600080549081600101905593506001600085815260200190815260200160002092508b83819055508a83600101819055503383600201819055508883600301819055508783600501819055508683600401819055508583600701819055508983600c01819055508483600d01819055506002600033600160a060020a03168152602001908152602001600020915081805490816001019055905083826001016000838152602001908152602001600020819055508333600160a060020a03167f882da991e52c8933ce57314c9ba3f934798d912d862790c40d0feeb7025af08a60006000a35b505050505050505050505050565b600060006000600034116103155761044e565b600160008581526020019081526020016000209250428360040154101561033b5761044d565b82600901805490816001019055915082600a0160008381526020019081526020016000209050338181905550348160010181905550806001015483600601818154019150819055508183600b01600033600160a060020a03168152602001908152602001600020819055508333600160a060020a03167fc5e578961e5bd7481ccf1d1bdfbad97b9f1ddfad520f061ca764a57018f3febe6000866006015481526020016000a3600083600d0154600160a060020a031614156103fc5761044c565b82600d0154600160a060020a03166249f068600060008260e060020a02600052600488815260200133600160a060020a03168152602001348152602001600060008660325a03f161044957005b50505b5b5b50505050565b60006000600160008481526020019081526020016000209150816004015442118015610487575081600501548260060154105b8015610497575060008260060154115b6104a0576105d8565b81600a01600083600b01600033600160a060020a03168152602001908152602001600020548152602001908152602001600020905060008160010154116104e6576105d7565b8054600160a060020a0316600082600101546000600060006000848787f161050a57005b505050806001015482600601818154039150819055508233600160a060020a03167fe139691e7435f1fb40ec50ed3729009226be49087fd00e9e5bac276c2a8f40cf6000846001015481526020016000a360008160010181905550600082600d0154600160a060020a03161415610580576105d6565b81600d0154600160a060020a031663b71f3cde600060008260e060020a0260005260048781526020018554600160a060020a0316815260200185600101548152602001600060008660325a03f16105d357005b50505b5b5b505050565b6000600160008381526020019081526020016000209050806005015481600601541015610609576106e4565b8060030154600160a060020a0316600082600601546000600060006000848787f161063057005b5050508133600160a060020a03167f6be92574b1386f424263a096e8b66ff6cc223ab0f9d18702563aa339a372cf986000846006015481526020016000a36000816006018190555060018160080181905550600081600d0154600160a060020a0316141561069d576106e3565b80600d0154600160a060020a031663484ec26c600060008260e060020a02600052600486815260200185600601548152602001600060008660325a03f16106e057005b50505b5b5050565b600060006002600085600160a060020a0316815260200190815260200160002090508060010160008481526020019081526020016000205491505092915050565b6000600060016000858152602001908152602001600020905080600a0160008481526020019081526020016000209150509291505056' -nameOpCodes(Buffer.from(data, 'hex')) +nameOpCodes(hexToBytes(data)) -function nameOpCodes(raw: Buffer) { - let pushData +function nameOpCodes(raw: Uint8Array) { + let pushData = new Uint8Array() for (let i = 0; i < raw.length; i++) { const pc = i @@ -23,15 +24,19 @@ function nameOpCodes(raw: Buffer) { // no destinations into the middle of PUSH if (curOpCode?.slice(0, 4) === 'PUSH') { const jumpNum = raw[pc] - 0x5f - pushData = raw.slice(pc + 1, pc + jumpNum + 1) + pushData = raw.subarray(pc + 1, pc + jumpNum + 1) i += jumpNum } console.log( - pad(pc, roundLog(raw.length, 10)) + ' ' + curOpCode + ' ' + pushData?.toString('hex') + pad(pc, roundLog(raw.length, 10)) + + ' ' + + curOpCode + + ' ' + + (pushData?.length > 0 ? bytesToHex(pushData as Uint8Array) : '') ) - pushData = '' + pushData = new Uint8Array() } } diff --git a/packages/evm/examples/runCode.ts b/packages/evm/examples/runCode.ts index 91a1c75f35..96a843a8c3 100644 --- a/packages/evm/examples/runCode.ts +++ b/packages/evm/examples/runCode.ts @@ -3,6 +3,7 @@ import { Chain, Common, Hardfork } from '@ethereumjs/common' import { EVM } from '@ethereumjs/evm' import { DefaultStateManager } from '@ethereumjs/statemanager' import { EEI } from '@ethereumjs/vm' +import { bytesToHex, hexToBytes } from 'ethereum-cryptography/utils' const main = async () => { const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.London }) @@ -29,11 +30,11 @@ const main = async () => { evm .runCode({ - code: Buffer.from(code.join(''), 'hex'), + code: hexToBytes(code.join('')), gasLimit: BigInt(0xffff), }) .then((results) => { - console.log(`Returned: ${results.returnValue.toString('hex')}`) + console.log(`Returned: ${bytesToHex(results.returnValue)}`) console.log(`gasUsed: ${results.executionGasUsed.toString()}`) }) .catch(console.error) diff --git a/packages/evm/package.json b/packages/evm/package.json index fb64a886f3..cffcd0d013 100644 --- a/packages/evm/package.json +++ b/packages/evm/package.json @@ -28,7 +28,8 @@ "src" ], "scripts": { - "build": "../../config/cli/ts-build.sh", + "rustbnHotFix": "sed -i -e \"s/.toString('hex')), 'hex'//g\" ../../node_modules/rustbn.js/index.js && sed -i -e \"s/Buffer.from(//g\" ../../node_modules/rustbn.js/index.js", + "build": "npm run rustbnHotFix && ../../config/cli/ts-build.sh", "clean": "../../config/cli/clean-package.sh", "coverage": "c8 --all --reporter=lcov --reporter=text npm run coverage:test", "coverage:test": "npm run test && cd ../vm && npm run tester -- --state", diff --git a/packages/evm/src/eof.ts b/packages/evm/src/eof.ts index 10217b11c6..1bbc738091 100644 --- a/packages/evm/src/eof.ts +++ b/packages/evm/src/eof.ts @@ -6,13 +6,13 @@ export const VERSION = 0x01 /** * - * @param container A `Buffer` containing bytecode to be checked for EOF1 compliance + * @param container A `Uint8Array` containing bytecode to be checked for EOF1 compliance * @returns an object containing the size of the code section and data sections for a valid * EOF1 container or else undefined if `container` is not valid EOF1 bytecode * * Note: See https://eips.ethereum.org/EIPS/eip-3540 for further details */ -export const codeAnalysis = (container: Buffer) => { +export const codeAnalysis = (container: Uint8Array) => { const secCode = 0x01 const secData = 0x02 const secTerminator = 0x00 @@ -62,7 +62,7 @@ export const codeAnalysis = (container: Buffer) => { return sectionSizes } -export const validOpcodes = (code: Buffer) => { +export const validOpcodes = (code: Uint8Array) => { // EIP-3670 - validate all opcodes const opcodes = new Set(handlers.keys()) opcodes.add(0xfe) // Add INVALID opcode to set @@ -92,13 +92,13 @@ export const validOpcodes = (code: Buffer) => { return true } -export const getEOFCode = (code: Buffer) => { +export const getEOFCode = (code: Uint8Array) => { const sectionSizes = codeAnalysis(code) if (sectionSizes === undefined) { return code } else { const codeStart = sectionSizes.data > 0 ? 10 : 7 - return code.slice(codeStart, codeStart + sectionSizes.code) + return code.subarray(codeStart, codeStart + sectionSizes.code) } } diff --git a/packages/evm/src/evm.ts b/packages/evm/src/evm.ts index 5cd91707c0..f822b54fb9 100644 --- a/packages/evm/src/evm.ts +++ b/packages/evm/src/evm.ts @@ -4,7 +4,9 @@ import { AsyncEventEmitter, KECCAK256_NULL, MAX_INTEGER, - bigIntToBuffer, + bigIntToBytes, + bytesToHex, + equalsBytes, generateAddress, generateAddress2, short, @@ -388,7 +390,7 @@ export class EVM implements EVMInterface { gasRefund: message.gasRefund, executionGasUsed: BigInt(0), exceptionError: errorMessage, // Only defined if addToBalance failed - returnValue: Buffer.alloc(0), + returnValue: new Uint8Array(0), }, } } @@ -430,7 +432,7 @@ export class EVM implements EVMInterface { return { createdAddress: message.to, execResult: { - returnValue: Buffer.alloc(0), + returnValue: new Uint8Array(0), exceptionError: new EvmError(ERROR.INITCODE_SIZE_VIOLATION), executionGasUsed: message.gasLimit, }, @@ -439,7 +441,7 @@ export class EVM implements EVMInterface { } message.code = message.data - message.data = Buffer.alloc(0) + message.data = new Uint8Array(0) message.to = await this._generateAddress(message) if (this.DEBUG) { debug(`Generated CREATE contract address ${message.to}`) @@ -449,7 +451,7 @@ export class EVM implements EVMInterface { // Check for collision if ( (toAccount.nonce && toAccount.nonce > BigInt(0)) || - !toAccount.codeHash.equals(KECCAK256_NULL) + !(equalsBytes(toAccount.codeHash, KECCAK256_NULL) === true) ) { if (this.DEBUG) { debug(`Returning on address collision`) @@ -457,7 +459,7 @@ export class EVM implements EVMInterface { return { createdAddress: message.to, execResult: { - returnValue: Buffer.alloc(0), + returnValue: new Uint8Array(0), exceptionError: new EvmError(ERROR.CREATE_COLLISION), executionGasUsed: message.gasLimit, }, @@ -507,7 +509,7 @@ export class EVM implements EVMInterface { executionGasUsed: BigInt(0), gasRefund: message.gasRefund, exceptionError: errorMessage, // only defined if addToBalance failed - returnValue: Buffer.alloc(0), + returnValue: new Uint8Array(0), }, } } @@ -562,7 +564,7 @@ export class EVM implements EVMInterface { // in the bytecode of the contract if ( !EOF.validOpcodes( - result.returnValue.slice(codeStart, codeStart + eof1CodeAnalysisResults.code) + result.returnValue.subarray(codeStart, codeStart + eof1CodeAnalysisResults.code) ) ) { result = { @@ -637,9 +639,9 @@ export class EVM implements EVMInterface { const env = { address: message.to ?? Address.zero(), caller: message.caller ?? Address.zero(), - callData: message.data ?? Buffer.from([0]), + callData: message.data ?? Uint8Array.from([0]), callValue: message.value ?? BigInt(0), - code: message.code as Buffer, + code: message.code as Uint8Array, isStatic: message.isStatic ?? false, depth: message.depth ?? 0, gasPrice: this._tx!.gasPrice, @@ -654,10 +656,10 @@ export class EVM implements EVMInterface { const interpreter = new Interpreter(this, this.eei, env, message.gasLimit) if (message.selfdestruct) { - interpreter._result.selfdestruct = message.selfdestruct as { [key: string]: Buffer } + interpreter._result.selfdestruct = message.selfdestruct as { [key: string]: Uint8Array } } - const interpreterRes = await interpreter.run(message.code as Buffer, opts) + const interpreterRes = await interpreter.run(message.code as Uint8Array, opts) let result = interpreter._result let gasUsed = message.gasLimit - interpreterRes.runState!.gasLeft @@ -688,7 +690,7 @@ export class EVM implements EVMInterface { gas: interpreterRes.runState?.gasLeft, executionGasUsed: gasUsed, gasRefund: interpreterRes.runState!.gasRefund, - returnValue: result.returnValue ? result.returnValue : Buffer.alloc(0), + returnValue: result.returnValue ? result.returnValue : new Uint8Array(0), } } @@ -750,7 +752,7 @@ export class EVM implements EVMInterface { if (!message.to && this._common.isActivatedEIP(2929) === true) { message.code = message.data - this.eei.addWarmedAddress((await this._generateAddress(message)).buf) + this.eei.addWarmedAddress((await this._generateAddress(message)).bytes) } await this.eei.checkpoint() @@ -853,7 +855,7 @@ export class EVM implements EVMInterface { * if no such precompile exists. */ getPrecompile(address: Address): PrecompileFunc | undefined { - return this.precompiles.get(address.buf.toString('hex')) + return this.precompiles.get(bytesToHex(address.bytes)) } /** @@ -861,7 +863,7 @@ export class EVM implements EVMInterface { */ protected runPrecompile( code: PrecompileFunc, - data: Buffer, + data: Uint8Array, gasLimit: bigint ): Promise | ExecResult { if (typeof code !== 'function') { @@ -900,11 +902,11 @@ export class EVM implements EVMInterface { protected async _generateAddress(message: Message): Promise
{ let addr if (message.salt) { - addr = generateAddress2(message.caller.buf, message.salt, message.code as Buffer) + addr = generateAddress2(message.caller.bytes, message.salt, message.code as Uint8Array) } else { const acc = await this.eei.getAccount(message.caller) const newNonce = acc.nonce - BigInt(1) - addr = generateAddress(message.caller.buf, bigIntToBuffer(newNonce)) + addr = generateAddress(message.caller.bytes, bigIntToBytes(newNonce)) } return new Address(addr) } @@ -995,7 +997,7 @@ export interface ExecResult { /** * Return value from the contract */ - returnValue: Buffer + returnValue: Uint8Array /** * Array of logs that the contract emitted */ @@ -1003,7 +1005,7 @@ export interface ExecResult { /** * A map from the accounts that have self-destructed to the addresses to send their funds to */ - selfdestruct?: { [k: string]: Buffer } + selfdestruct?: { [k: string]: Uint8Array } /** * The gas refund counter */ @@ -1012,7 +1014,7 @@ export interface ExecResult { export function OOGResult(gasLimit: bigint): ExecResult { return { - returnValue: Buffer.alloc(0), + returnValue: new Uint8Array(0), executionGasUsed: gasLimit, exceptionError: new EvmError(ERROR.OUT_OF_GAS), } @@ -1020,7 +1022,7 @@ export function OOGResult(gasLimit: bigint): ExecResult { // CodeDeposit OOG Result export function COOGResult(gasUsedCreateCode: bigint): ExecResult { return { - returnValue: Buffer.alloc(0), + returnValue: new Uint8Array(0), executionGasUsed: gasUsedCreateCode, exceptionError: new EvmError(ERROR.CODESTORE_OUT_OF_GAS), } @@ -1028,7 +1030,7 @@ export function COOGResult(gasUsedCreateCode: bigint): ExecResult { export function INVALID_BYTECODE_RESULT(gasLimit: bigint): ExecResult { return { - returnValue: Buffer.alloc(0), + returnValue: new Uint8Array(0), executionGasUsed: gasLimit, exceptionError: new EvmError(ERROR.INVALID_BYTECODE_RESULT), } @@ -1036,7 +1038,7 @@ export function INVALID_BYTECODE_RESULT(gasLimit: bigint): ExecResult { export function INVALID_EOF_RESULT(gasLimit: bigint): ExecResult { return { - returnValue: Buffer.alloc(0), + returnValue: new Uint8Array(0), executionGasUsed: gasLimit, exceptionError: new EvmError(ERROR.INVALID_EOF_FORMAT), } @@ -1044,7 +1046,7 @@ export function INVALID_EOF_RESULT(gasLimit: bigint): ExecResult { export function CodesizeExceedsMaximumError(gasUsed: bigint): ExecResult { return { - returnValue: Buffer.alloc(0), + returnValue: new Uint8Array(0), executionGasUsed: gasUsed, exceptionError: new EvmError(ERROR.CODESIZE_EXCEEDS_MAXIMUM), } @@ -1052,7 +1054,7 @@ export function CodesizeExceedsMaximumError(gasUsed: bigint): ExecResult { export function EvmErrorResult(error: EvmError, gasUsed: bigint): ExecResult { return { - returnValue: Buffer.alloc(0), + returnValue: new Uint8Array(0), executionGasUsed: gasUsed, exceptionError: error, } diff --git a/packages/evm/src/interpreter.ts b/packages/evm/src/interpreter.ts index ed09149f38..1b0e563aab 100644 --- a/packages/evm/src/interpreter.ts +++ b/packages/evm/src/interpreter.ts @@ -1,5 +1,5 @@ import { ConsensusAlgorithm } from '@ethereumjs/common' -import { MAX_UINT64, bigIntToHex, bufferToBigInt, intToHex } from '@ethereumjs/util' +import { MAX_UINT64, bigIntToHex, bytesToBigInt, bytesToHex, intToHex } from '@ethereumjs/util' import { debug as createDebugLogger } from 'debug' import { EOF } from './eof' @@ -26,19 +26,19 @@ export interface InterpreterOpts { */ export interface RunResult { logs: Log[] - returnValue?: Buffer + returnValue?: Uint8Array /** * A map from the accounts that have self-destructed to the addresses to send their funds to */ - selfdestruct: { [k: string]: Buffer } + selfdestruct: { [k: string]: Uint8Array } } export interface Env { address: Address caller: Address - callData: Buffer + callData: Uint8Array callValue: bigint - code: Buffer + code: Uint8Array isStatic: boolean depth: number gasPrice: bigint @@ -47,8 +47,8 @@ export interface Env { contract: Account codeAddress: Address /* Different than address for DELEGATECALL and CALLCODE */ gasRefund: bigint /* Current value (at begin of the frame) of the gas refund */ - containerCode?: Buffer /** Full container code for EOF1 contracts */ - versionedHashes: Buffer[] /** Versioned hashes for blob transactions */ + containerCode?: Uint8Array /** Full container code for EOF1 contracts */ + versionedHashes: Uint8Array[] /** Versioned hashes for blob transactions */ } export interface RunState { @@ -59,7 +59,7 @@ export interface RunState { highestMemCost: bigint stack: Stack returnStack: Stack - code: Buffer + code: Uint8Array shouldDoJumpAnalysis: boolean validJumps: Uint8Array // array of values where validJumps[index] has value 0 (default), 1 (jumpdest), 2 (beginsub) eei: EEIInterface @@ -69,7 +69,7 @@ export interface RunState { gasRefund: bigint // Tracks the current refund gasLeft: bigint // Current gas left auth?: Address /** EIP-3074 AUTH parameter */ - returnBuffer: Buffer /* Current bytes in the return buffer. Cleared each time a CALL/CREATE is made in the current frame. */ + returnBytes: Uint8Array /* Current bytes in the return Uint8Array. Cleared each time a CALL/CREATE is made in the current frame. */ } export interface InterpreterResult { @@ -93,7 +93,7 @@ export interface InterpreterStep { } account: Account address: Address - memory: Buffer + memory: Uint8Array memoryWordCount: bigint codeAddress: Address } @@ -131,7 +131,7 @@ export class Interpreter { highestMemCost: BigInt(0), stack: new Stack(), returnStack: new Stack(1023), // 1023 return stack height limit per EIP 2315 spec - code: Buffer.alloc(0), + code: new Uint8Array(0), validJumps: Uint8Array.from([]), eei: this._eei, env, @@ -139,7 +139,7 @@ export class Interpreter { interpreter: this, gasRefund: env.gasRefund, gasLeft, - returnBuffer: Buffer.alloc(0), + returnBytes: new Uint8Array(0), } this._env = env this._result = { @@ -149,7 +149,7 @@ export class Interpreter { } } - async run(code: Buffer, opts: InterpreterOpts = {}): Promise { + async run(code: Uint8Array, opts: InterpreterOpts = {}): Promise { if (!this._common.isActivatedEIP(3540) || code[0] !== EOF.FORMAT) { // EIP-3540 isn't active and first byte is not 0xEF - treat as legacy bytecode this._runState.code = code @@ -180,10 +180,10 @@ export class Interpreter { if (codeSections.data) { // Set code to EOF container code section which starts at byte position 10 if data section is present - this._runState.code = code.slice(10, 10 + codeSections!.code) + this._runState.code = code.subarray(10, 10 + codeSections!.code) } else { // Set code to EOF container code section which starts at byte position 7 if no data section is present - this._runState.code = code.slice(7, 7 + codeSections!.code) + this._runState.code = code.subarray(7, 7 + codeSections!.code) } } this._runState.programCounter = opts.pc ?? this._runState.programCounter @@ -349,12 +349,12 @@ export class Interpreter { * @property {BigInt} gasLeft amount of gasLeft * @property {BigInt} gasRefund gas refund * @property {StateManager} stateManager a {@link StateManager} instance - * @property {Array} stack an `Array` of `Buffers` containing the stack + * @property {Array} stack an `Array` of `Uint8Arrays` containing the stack * @property {Array} returnStack the return stack * @property {Account} account the Account which owns the code running * @property {Address} address the address of the `account` * @property {Number} depth the current number of calls deep the contract is - * @property {Buffer} memory the memory of the EVM as a `buffer` + * @property {Uint8Array} memory the memory of the EVM as a `Uint8Array` * @property {BigInt} memoryWordCount current size of memory in words * @property {Address} codeAddress the address of the code which is currently being ran (this differs from `address` in a `DELEGATECALL` and `CALLCODE` call) */ @@ -362,7 +362,7 @@ export class Interpreter { } // Returns all valid jump and jumpsub destinations. - _getValidJumpDests(code: Buffer) { + _getValidJumpDests(code: Uint8Array) { const jumps = new Uint8Array(code.length).fill(0) for (let i = 0; i < code.length; i++) { @@ -471,7 +471,7 @@ export class Interpreter { /** * Store 256-bit a value in memory to persistent storage. */ - async storageStore(key: Buffer, value: Buffer): Promise { + async storageStore(key: Uint8Array, value: Uint8Array): Promise { await this._eei.storageStore(this._env.address, key, value) const account = await this._eei.getAccount(this._env.address) this._env.contract = account @@ -482,7 +482,7 @@ export class Interpreter { * @param key - Storage key * @param original - If true, return the original storage value (default: false) */ - async storageLoad(key: Buffer, original = false): Promise { + async storageLoad(key: Uint8Array, original = false): Promise { return this._eei.storageLoad(this._env.address, key, original) } @@ -492,7 +492,7 @@ export class Interpreter { * @param key Storage key * @param value Storage value */ - transientStorageStore(key: Buffer, value: Buffer): void { + transientStorageStore(key: Uint8Array, value: Uint8Array): void { return this._evm._transientStorage.put(this._env.address, key, value) } @@ -501,7 +501,7 @@ export class Interpreter { * @param address Address to use * @param key Storage key */ - transientStorageLoad(key: Buffer): Buffer { + transientStorageLoad(key: Uint8Array): Uint8Array { return this._evm._transientStorage.get(this._env.address, key) } @@ -509,7 +509,7 @@ export class Interpreter { * Set the returning output data for the execution. * @param returnData - Output data to return */ - finish(returnData: Buffer): void { + finish(returnData: Uint8Array): void { this._result.returnValue = returnData trap(ERROR.STOP) } @@ -519,7 +519,7 @@ export class Interpreter { * execution immediately and set the execution result to "reverted". * @param returnData - Output data to return */ - revert(returnData: Buffer): void { + revert(returnData: Uint8Array): void { this._result.returnValue = returnData trap(ERROR.REVERT) } @@ -550,7 +550,7 @@ export class Interpreter { * Returns input data in current environment. This pertains to the input * data passed with the message call instruction or transaction. */ - getCallData(): Buffer { + getCallData(): Uint8Array { return this._env.callData } @@ -567,7 +567,7 @@ export class Interpreter { * that is directly responsible for this execution. */ getCaller(): bigint { - return bufferToBigInt(this._env.caller.buf) + return bytesToBigInt(this._env.caller.bytes) } /** @@ -580,7 +580,7 @@ export class Interpreter { /** * Returns the code running in current environment. */ - getCode(): Buffer { + getCode(): Uint8Array { return this._env.containerCode ?? this._env.code } @@ -597,7 +597,7 @@ export class Interpreter { * Note: create only fills the return data buffer in case of a failure. */ getReturnDataSize(): bigint { - return BigInt(this._runState.returnBuffer.length) + return BigInt(this._runState.returnBytes.length) } /** @@ -605,8 +605,8 @@ export class Interpreter { * from last executed call, callCode, callDelegate, callStatic or create. * Note: create only fills the return data buffer in case of a failure. */ - getReturnData(): Buffer { - return this._runState.returnBuffer + getReturnData(): Uint8Array { + return this._runState.returnBytes } /** @@ -629,7 +629,7 @@ export class Interpreter { * non-empty associated code. */ getTxOrigin(): bigint { - return bufferToBigInt(this._env.origin.buf) + return bytesToBigInt(this._env.origin.bytes) } /** @@ -649,7 +649,7 @@ export class Interpreter { } else { coinbase = this._env.block.header.coinbase } - return bufferToBigInt(coinbase.toBuffer()) + return bytesToBigInt(coinbase.toBytes()) } /** @@ -670,7 +670,7 @@ export class Interpreter { * Returns the block's prevRandao field. */ getBlockPrevRandao(): bigint { - return bufferToBigInt(this._env.block.header.prevRandao) + return bytesToBigInt(this._env.block.header.prevRandao) } /** @@ -703,7 +703,7 @@ export class Interpreter { /** * Sends a message with arbitrary data to a given address path. */ - async call(gasLimit: bigint, address: Address, value: bigint, data: Buffer): Promise { + async call(gasLimit: bigint, address: Address, value: bigint, data: Uint8Array): Promise { const msg = new Message({ caller: this._env.address, gasLimit, @@ -720,7 +720,12 @@ export class Interpreter { /** * Sends a message with arbitrary data to a given address path. */ - async authcall(gasLimit: bigint, address: Address, value: bigint, data: Buffer): Promise { + async authcall( + gasLimit: bigint, + address: Address, + value: bigint, + data: Uint8Array + ): Promise { const msg = new Message({ caller: this._runState.auth, gasLimit, @@ -738,7 +743,12 @@ export class Interpreter { /** * Message-call into this account with an alternative account's code. */ - async callCode(gasLimit: bigint, address: Address, value: bigint, data: Buffer): Promise { + async callCode( + gasLimit: bigint, + address: Address, + value: bigint, + data: Uint8Array + ): Promise { const msg = new Message({ caller: this._env.address, gasLimit, @@ -762,7 +772,7 @@ export class Interpreter { gasLimit: bigint, address: Address, value: bigint, - data: Buffer + data: Uint8Array ): Promise { const msg = new Message({ caller: this._env.address, @@ -785,7 +795,7 @@ export class Interpreter { gasLimit: bigint, address: Address, value: bigint, - data: Buffer + data: Uint8Array ): Promise { const msg = new Message({ caller: this._env.caller, @@ -807,8 +817,8 @@ export class Interpreter { msg.selfdestruct = selfdestruct msg.gasRefund = this._runState.gasRefund - // empty the return data buffer - this._runState.returnBuffer = Buffer.alloc(0) + // empty the return data Uint8Array + this._runState.returnBytes = new Uint8Array(0) // Check if account has enough ether and max depth not exceeded if ( @@ -833,7 +843,7 @@ export class Interpreter { (!results.execResult.exceptionError || results.execResult.exceptionError.error === ERROR.REVERT) ) { - this._runState.returnBuffer = results.execResult.returnValue + this._runState.returnBytes = results.execResult.returnValue } if (!results.execResult.exceptionError) { @@ -850,13 +860,18 @@ export class Interpreter { /** * Creates a new contract with a given value. */ - async create(gasLimit: bigint, value: bigint, data: Buffer, salt?: Buffer): Promise { + async create( + gasLimit: bigint, + value: bigint, + data: Uint8Array, + salt?: Uint8Array + ): Promise { const selfdestruct = { ...this._result.selfdestruct } const caller = this._env.address const depth = this._env.depth + 1 // empty the return data buffer - this._runState.returnBuffer = Buffer.alloc(0) + this._runState.returnBytes = new Uint8Array(0) // Check if account has enough ether and max depth not exceeded if ( @@ -908,7 +923,7 @@ export class Interpreter { results.execResult.exceptionError && results.execResult.exceptionError.error === ERROR.REVERT ) { - this._runState.returnBuffer = results.execResult.returnValue + this._runState.returnBytes = results.execResult.returnValue } if ( @@ -922,7 +937,7 @@ export class Interpreter { this._runState.gasRefund = results.execResult.gasRefund ?? BigInt(0) if (results.createdAddress) { // push the created address to the stack - return bufferToBigInt(results.createdAddress.buf) + return bytesToBigInt(results.createdAddress.bytes) } } @@ -933,7 +948,12 @@ export class Interpreter { * Creates a new contract with a given value. Generates * a deterministic address via CREATE2 rules. */ - async create2(gasLimit: bigint, value: bigint, data: Buffer, salt: Buffer): Promise { + async create2( + gasLimit: bigint, + value: bigint, + data: Uint8Array, + salt: Uint8Array + ): Promise { return this.create(gasLimit, value, data, salt) } @@ -949,11 +969,11 @@ export class Interpreter { async _selfDestruct(toAddress: Address): Promise { // only add to refund if this is the first selfdestruct for the address - if (this._result.selfdestruct[this._env.address.buf.toString('hex')] === undefined) { + if (this._result.selfdestruct[bytesToHex(this._env.address.bytes)] === undefined) { this.refundGas(this._common.param('gasPrices', 'selfdestructRefund')) } - this._result.selfdestruct[this._env.address.buf.toString('hex')] = toAddress.buf + this._result.selfdestruct[bytesToHex(this._env.address.bytes)] = toAddress.bytes // Add to beneficiary balance const toAccount = await this._eei.getAccount(toAddress) @@ -971,7 +991,7 @@ export class Interpreter { /** * Creates a new log in the current environment. */ - log(data: Buffer, numberOfTopics: number, topics: Buffer[]): void { + log(data: Uint8Array, numberOfTopics: number, topics: Uint8Array[]): void { if (numberOfTopics < 0 || numberOfTopics > 4) { trap(ERROR.OUT_OF_RANGE) } @@ -980,7 +1000,7 @@ export class Interpreter { trap(ERROR.INTERNAL_ERROR) } - const log: Log = [this._env.address.buf, topics, data] + const log: Log = [this._env.address.bytes, topics, data] this._result.logs.push(log) } diff --git a/packages/evm/src/memory.ts b/packages/evm/src/memory.ts index c063df3738..85eafd0604 100644 --- a/packages/evm/src/memory.ts +++ b/packages/evm/src/memory.ts @@ -1,3 +1,5 @@ +import { concatBytesNoTypeCheck } from '@ethereumjs/util' + const ceil = (value: number, ceiling: number): number => { const r = value % ceiling if (r === 0) { @@ -14,10 +16,10 @@ const CONTAINER_SIZE = 8192 * for the ethereum virtual machine. */ export class Memory { - _store: Buffer + _store: Uint8Array constructor() { - this._store = Buffer.alloc(0) + this._store = new Uint8Array(0) } /** @@ -32,10 +34,10 @@ export class Memory { const newSize = ceil(offset + size, 32) const sizeDiff = newSize - this._store.length if (sizeDiff > 0) { - this._store = Buffer.concat([ + this._store = concatBytesNoTypeCheck( this._store, - Buffer.alloc(Math.ceil(sizeDiff / CONTAINER_SIZE) * CONTAINER_SIZE), - ]) + new Uint8Array(Math.ceil(sizeDiff / CONTAINER_SIZE) * CONTAINER_SIZE) + ) } } @@ -45,7 +47,7 @@ export class Memory { * @param size - How many bytes to write * @param value - Value */ - write(offset: number, size: number, value: Buffer) { + write(offset: number, size: number, value: Uint8Array) { if (size === 0) { return } @@ -55,24 +57,27 @@ export class Memory { if (value.length !== size) throw new Error('Invalid value size') if (offset + size > this._store.length) throw new Error('Value exceeds memory capacity') - value.copy(this._store, offset) + this._store.set(value, offset) } /** - * Reads a slice of memory from `offset` till `offset + size` as a `Buffer`. + * Reads a slice of memory from `offset` till `offset + size` as a `Uint8Array`. * It fills up the difference between memory's length and `offset + size` with zeros. * @param offset - Starting position * @param size - How many bytes to read * @param avoidCopy - Avoid memory copy if possible for performance reasons (optional) */ - read(offset: number, size: number, avoidCopy?: boolean): Buffer { + read(offset: number, size: number, avoidCopy?: boolean): Uint8Array { this.extend(offset, size) - const loaded = this._store.slice(offset, offset + size) + const loaded = this._store.subarray(offset, offset + size) if (avoidCopy === true) { return loaded } + const returnBytes = new Uint8Array(size) + // Copy the stored "buffer" from memory into the return Buffer + returnBytes.set(loaded) - return Buffer.from(loaded) + return returnBytes } } diff --git a/packages/evm/src/message.ts b/packages/evm/src/message.ts index 5928bb7385..e8d43af877 100644 --- a/packages/evm/src/message.ts +++ b/packages/evm/src/message.ts @@ -5,7 +5,7 @@ import type { PrecompileFunc } from './precompiles' const defaults = { value: BigInt(0), caller: Address.zero(), - data: Buffer.alloc(0), + data: new Uint8Array(0), depth: 0, isStatic: false, isCompiled: false, @@ -18,21 +18,21 @@ interface MessageOpts { value?: bigint caller?: Address gasLimit: bigint - data?: Buffer + data?: Uint8Array depth?: number - code?: Buffer | PrecompileFunc + code?: Uint8Array | PrecompileFunc codeAddress?: Address isStatic?: boolean isCompiled?: boolean - salt?: Buffer + salt?: Uint8Array /** * A map of addresses to selfdestruct, see {@link Message.selfdestruct} */ - selfdestruct?: { [key: string]: boolean } | { [key: string]: Buffer } + selfdestruct?: { [key: string]: boolean } | { [key: string]: Uint8Array } delegatecall?: boolean authcallOrigin?: Address gasRefund?: bigint - versionedHashes?: Buffer[] + versionedHashes?: Uint8Array[] } export class Message { @@ -40,19 +40,19 @@ export class Message { value: bigint caller: Address gasLimit: bigint - data: Buffer + data: Uint8Array depth: number - code?: Buffer | PrecompileFunc + code?: Uint8Array | PrecompileFunc _codeAddress?: Address isStatic: boolean isCompiled: boolean - salt?: Buffer - containerCode?: Buffer /** container code for EOF1 contracts - used by CODECOPY/CODESIZE */ + salt?: Uint8Array + containerCode?: Uint8Array /** container code for EOF1 contracts - used by CODECOPY/CODESIZE */ /** * Map of addresses to selfdestruct. Key is the unprefixed address. - * Value is a boolean when marked for destruction and replaced with a Buffer containing the address where the remaining funds are sent. + * Value is a boolean when marked for destruction and replaced with a Uint8Array containing the address where the remaining funds are sent. */ - selfdestruct?: { [key: string]: boolean } | { [key: string]: Buffer } + selfdestruct?: { [key: string]: boolean } | { [key: string]: Uint8Array } delegatecall: boolean /** * This is used to store the origin of the AUTHCALL, @@ -63,7 +63,7 @@ export class Message { /** * List of versioned hashes if message is a blob transaction in the outer VM */ - versionedHashes?: Buffer[] + versionedHashes?: Uint8Array[] constructor(opts: MessageOpts) { this.to = opts.to diff --git a/packages/evm/src/opcodes/EIP1283.ts b/packages/evm/src/opcodes/EIP1283.ts index b4341ae201..8682811eb1 100644 --- a/packages/evm/src/opcodes/EIP1283.ts +++ b/packages/evm/src/opcodes/EIP1283.ts @@ -1,3 +1,5 @@ +import { equalsBytes } from 'ethereum-cryptography/utils' + import type { RunState } from '../interpreter' import type { Common } from '@ethereumjs/common' @@ -5,24 +7,24 @@ import type { Common } from '@ethereumjs/common' * Adjusts gas usage and refunds of SStore ops per EIP-1283 (Constantinople) * * @param {RunState} runState - * @param {Buffer} currentStorage - * @param {Buffer} originalStorage - * @param {Buffer} value + * @param {Uint8Array} currentStorage + * @param {Uint8Array} originalStorage + * @param {Uint8Array} value * @param {Common} common */ export function updateSstoreGasEIP1283( runState: RunState, - currentStorage: Buffer, - originalStorage: Buffer, - value: Buffer, + currentStorage: Uint8Array, + originalStorage: Uint8Array, + value: Uint8Array, common: Common ) { - if (currentStorage.equals(value)) { + if (equalsBytes(currentStorage, value)) { // If current value equals new value (this is a no-op), 200 gas is deducted. return common.param('gasPrices', 'netSstoreNoopGas') } // If current value does not equal new value - if (originalStorage.equals(currentStorage)) { + if (equalsBytes(originalStorage, currentStorage)) { // If original value equals current value (this storage slot has not been changed by the current execution context) if (originalStorage.length === 0) { // If original value is 0, 20000 gas is deducted. @@ -55,7 +57,7 @@ export function updateSstoreGasEIP1283( ) } } - if (originalStorage.equals(value)) { + if (equalsBytes(originalStorage, value)) { // If original value equals new value (this storage slot is reset) if (originalStorage.length === 0) { // If original value is 0, add 19800 gas to refund counter. diff --git a/packages/evm/src/opcodes/EIP2200.ts b/packages/evm/src/opcodes/EIP2200.ts index 3b6e9efe46..5b548fde03 100644 --- a/packages/evm/src/opcodes/EIP2200.ts +++ b/packages/evm/src/opcodes/EIP2200.ts @@ -1,3 +1,5 @@ +import { equalsBytes } from 'ethereum-cryptography/utils' + import { ERROR } from '../exceptions' import { adjustSstoreGasEIP2929 } from './EIP2929' @@ -10,17 +12,17 @@ import type { Common } from '@ethereumjs/common' * Adjusts gas usage and refunds of SStore ops per EIP-2200 (Istanbul) * * @param {RunState} runState - * @param {Buffer} currentStorage - * @param {Buffer} originalStorage - * @param {Buffer} value + * @param {Uint8Array} currentStorage + * @param {Uint8Array} originalStorage + * @param {Uint8Array} value * @param {Common} common */ export function updateSstoreGasEIP2200( runState: RunState, - currentStorage: Buffer, - originalStorage: Buffer, - value: Buffer, - key: Buffer, + currentStorage: Uint8Array, + originalStorage: Uint8Array, + value: Uint8Array, + key: Uint8Array, common: Common ) { // Fail if not enough gas is left @@ -29,11 +31,11 @@ export function updateSstoreGasEIP2200( } // Noop - if (currentStorage.equals(value)) { + if (equalsBytes(currentStorage, value)) { const sstoreNoopCost = common.param('gasPrices', 'sstoreNoopGasEIP2200') return adjustSstoreGasEIP2929(runState, key, sstoreNoopCost, 'noop', common) } - if (originalStorage.equals(currentStorage)) { + if (equalsBytes(originalStorage, currentStorage)) { // Create slot if (originalStorage.length === 0) { return common.param('gasPrices', 'sstoreInitGasEIP2200') @@ -63,7 +65,7 @@ export function updateSstoreGasEIP2200( ) } } - if (originalStorage.equals(value)) { + if (equalsBytes(originalStorage, value)) { if (originalStorage.length === 0) { // Reset to original non-existent slot const sstoreInitRefund = common.param('gasPrices', 'sstoreInitRefundEIP2200') diff --git a/packages/evm/src/opcodes/EIP2929.ts b/packages/evm/src/opcodes/EIP2929.ts index 8e6ee5c3d2..bb702ff6e6 100644 --- a/packages/evm/src/opcodes/EIP2929.ts +++ b/packages/evm/src/opcodes/EIP2929.ts @@ -22,7 +22,7 @@ export function accessAddressEIP2929( if (common.isActivatedEIP(2929) === false) return BigInt(0) const eei = runState.eei - const addressStr = address.buf + const addressStr = address.bytes // Cold if (!eei.isWarmedAddress(addressStr)) { @@ -45,19 +45,19 @@ export function accessAddressEIP2929( * Adjusts cost incurred for executing opcode based on whether storage read * is warm/cold. (EIP 2929) * @param {RunState} runState - * @param {Buffer} key (to storage slot) + * @param {Uint8Array} key (to storage slot) * @param {Common} common */ export function accessStorageEIP2929( runState: RunState, - key: Buffer, + key: Uint8Array, isSstore: boolean, common: Common ): bigint { if (common.isActivatedEIP(2929) === false) return BigInt(0) const eei = runState.eei - const address = runState.interpreter.getAddress().buf + const address = runState.interpreter.getAddress().bytes const slotIsCold = !eei.isWarmedStorage(address, key) // Cold (SLOAD and SSTORE) @@ -74,7 +74,7 @@ export function accessStorageEIP2929( * Adjusts cost of SSTORE_RESET_GAS or SLOAD (aka sstorenoop) (EIP-2200) downward when storage * location is already warm * @param {RunState} runState - * @param {Buffer} key storage slot + * @param {Uint8Array} key storage slot * @param {BigInt} defaultCost SSTORE_RESET_GAS / SLOAD * @param {string} costName parameter name ('noop') * @param {Common} common @@ -82,7 +82,7 @@ export function accessStorageEIP2929( */ export function adjustSstoreGasEIP2929( runState: RunState, - key: Buffer, + key: Uint8Array, defaultCost: bigint, costName: string, common: Common @@ -90,7 +90,7 @@ export function adjustSstoreGasEIP2929( if (common.isActivatedEIP(2929) === false) return defaultCost const eei = runState.eei - const address = runState.interpreter.getAddress().buf + const address = runState.interpreter.getAddress().bytes const warmRead = common.param('gasPrices', 'warmstorageread') const coldSload = common.param('gasPrices', 'coldsload') diff --git a/packages/evm/src/opcodes/functions.ts b/packages/evm/src/opcodes/functions.ts index 770ac3d83b..656b760e81 100644 --- a/packages/evm/src/opcodes/functions.ts +++ b/packages/evm/src/opcodes/functions.ts @@ -3,20 +3,21 @@ import { MAX_INTEGER_BIGINT, SECP256K1_ORDER_DIV_2, TWO_POW256, - bigIntToBuffer, - bufferToBigInt, + bigIntToBytes, + bytesToBigInt, + concatBytesNoTypeCheck, ecrecover, publicToAddress, setLengthLeft, setLengthRight, } from '@ethereumjs/util' import { keccak256 } from 'ethereum-cryptography/keccak' -import { bytesToHex } from 'ethereum-cryptography/utils' +import { bytesToHex, hexToBytes } from 'ethereum-cryptography/utils' import { ERROR } from '../exceptions' import { - addressToBuffer, + addresstoBytes, describeLocation, exponentiation, fromTwos, @@ -32,7 +33,7 @@ import { import type { RunState } from '../interpreter' import type { Common } from '@ethereumjs/common' -const EIP3074MAGIC = Buffer.from('03', 'hex') +const EIP3074MAGIC = hexToBytes('03') export interface SyncOpHandler { (runState: RunState, common: Common): void @@ -369,7 +370,7 @@ export const handlers: Map = new Map([ 0x20, function (runState) { const [offset, length] = runState.stack.popN(2) - let data = Buffer.alloc(0) + let data = new Uint8Array(0) if (length !== BigInt(0)) { data = runState.memory.read(Number(offset), Number(length)) } @@ -382,7 +383,7 @@ export const handlers: Map = new Map([ [ 0x30, function (runState) { - const address = bufferToBigInt(runState.interpreter.getAddress().buf) + const address = bytesToBigInt(runState.interpreter.getAddress().bytes) runState.stack.push(address) }, ], @@ -391,7 +392,7 @@ export const handlers: Map = new Map([ 0x31, async function (runState) { const addressBigInt = runState.stack.pop() - const address = new Address(addressToBuffer(addressBigInt)) + const address = new Address(addresstoBytes(addressBigInt)) const balance = await runState.interpreter.getExternalBalance(address) runState.stack.push(balance) }, @@ -428,9 +429,9 @@ export const handlers: Map = new Map([ } const i = Number(pos) - let loaded = runState.interpreter.getCallData().slice(i, i + 32) - loaded = loaded.length ? loaded : Buffer.from([0]) - let r = bufferToBigInt(loaded) + let loaded = runState.interpreter.getCallData().subarray(i, i + 32) + loaded = loaded.length ? loaded : Uint8Array.from([0]) + let r = bytesToBigInt(loaded) if (loaded.length < 32) { r = r << (BigInt(8) * BigInt(32 - loaded.length)) } @@ -486,7 +487,7 @@ export const handlers: Map = new Map([ async function (runState) { const addressBigInt = runState.stack.pop() const size = BigInt( - (await runState.eei.getContractCode(new Address(addressToBuffer(addressBigInt)))).length + (await runState.eei.getContractCode(new Address(addresstoBytes(addressBigInt)))).length ) runState.stack.push(size) }, @@ -498,7 +499,7 @@ export const handlers: Map = new Map([ const [addressBigInt, memOffset, codeOffset, dataLength] = runState.stack.popN(4) if (dataLength !== BigInt(0)) { - const code = await runState.eei.getContractCode(new Address(addressToBuffer(addressBigInt))) + const code = await runState.eei.getContractCode(new Address(addresstoBytes(addressBigInt))) const data = getDataSlice(code, codeOffset, dataLength) const memOffsetNum = Number(memOffset) @@ -512,14 +513,14 @@ export const handlers: Map = new Map([ 0x3f, async function (runState) { const addressBigInt = runState.stack.pop() - const address = new Address(addressToBuffer(addressBigInt)) + const address = new Address(addresstoBytes(addressBigInt)) const account = await runState.eei.getAccount(address) if (account.isEmpty()) { runState.stack.push(BigInt(0)) return } - runState.stack.push(BigInt('0x' + account.codeHash.toString('hex'))) + runState.stack.push(BigInt('0x' + bytesToHex(account.codeHash))) }, ], // 0x3d: RETURNDATASIZE @@ -638,7 +639,7 @@ export const handlers: Map = new Map([ function (runState) { const index = runState.stack.pop() if (runState.env.versionedHashes.length > Number(index)) { - runState.stack.push(bufferToBigInt(runState.env.versionedHashes[Number(index)])) + runState.stack.push(bytesToBigInt(runState.env.versionedHashes[Number(index)])) } else { runState.stack.push(BigInt(0)) } @@ -658,7 +659,7 @@ export const handlers: Map = new Map([ function (runState) { const pos = runState.stack.pop() const word = runState.memory.read(Number(pos), 32, true) - runState.stack.push(bufferToBigInt(word)) + runState.stack.push(bytesToBigInt(word)) }, ], // 0x52: MSTORE @@ -666,7 +667,7 @@ export const handlers: Map = new Map([ 0x52, function (runState) { const [offset, word] = runState.stack.popN(2) - const buf = setLengthLeft(bigIntToBuffer(word), 32) + const buf = setLengthLeft(bigIntToBytes(word), 32) const offsetNum = Number(offset) runState.memory.write(offsetNum, 32, buf) }, @@ -677,7 +678,7 @@ export const handlers: Map = new Map([ function (runState) { const [offset, byte] = runState.stack.popN(2) - const buf = bigIntToBuffer(byte & BigInt(0xff)) + const buf = bigIntToBytes(byte & BigInt(0xff)) const offsetNum = Number(offset) runState.memory.write(offsetNum, 1, buf) }, @@ -687,9 +688,9 @@ export const handlers: Map = new Map([ 0x54, async function (runState) { const key = runState.stack.pop() - const keyBuf = setLengthLeft(bigIntToBuffer(key), 32) + const keyBuf = setLengthLeft(bigIntToBytes(key), 32) const value = await runState.interpreter.storageLoad(keyBuf) - const valueBigInt = value.length ? bufferToBigInt(value) : BigInt(0) + const valueBigInt = value.length ? bytesToBigInt(value) : BigInt(0) runState.stack.push(valueBigInt) }, ], @@ -699,13 +700,13 @@ export const handlers: Map = new Map([ async function (runState) { const [key, val] = runState.stack.popN(2) - const keyBuf = setLengthLeft(bigIntToBuffer(key), 32) + const keyBuf = setLengthLeft(bigIntToBytes(key), 32) // NOTE: this should be the shortest representation let value if (val === BigInt(0)) { - value = Buffer.from([]) + value = Uint8Array.from([]) } else { - value = bigIntToBuffer(val) + value = bigIntToBytes(val) } await runState.interpreter.storageStore(keyBuf, value) @@ -830,8 +831,8 @@ export const handlers: Map = new Map([ trap(ERROR.OUT_OF_RANGE) } - const loaded = bufferToBigInt( - runState.code.slice(runState.programCounter, runState.programCounter + numToPush) + const loaded = bytesToBigInt( + runState.code.subarray(runState.programCounter, runState.programCounter + numToPush) ) runState.programCounter += numToPush runState.stack.push(loaded) @@ -863,10 +864,10 @@ export const handlers: Map = new Map([ const topics = runState.stack.popN(topicsCount) const topicsBuf = topics.map(function (a: bigint) { - return setLengthLeft(bigIntToBuffer(a), 32) + return setLengthLeft(bigIntToBytes(a), 32) }) - let mem = Buffer.alloc(0) + let mem = new Uint8Array(0) if (memLength !== BigInt(0)) { mem = runState.memory.read(Number(memOffset), Number(memLength)) } @@ -879,9 +880,9 @@ export const handlers: Map = new Map([ 0xb3, function (runState) { const key = runState.stack.pop() - const keyBuf = setLengthLeft(bigIntToBuffer(key), 32) + const keyBuf = setLengthLeft(bigIntToBytes(key), 32) const value = runState.interpreter.transientStorageLoad(keyBuf) - const valueBN = value.length ? bufferToBigInt(value) : BigInt(0) + const valueBN = value.length ? bytesToBigInt(value) : BigInt(0) runState.stack.push(valueBN) }, ], @@ -894,13 +895,13 @@ export const handlers: Map = new Map([ } const [key, val] = runState.stack.popN(2) - const keyBuf = setLengthLeft(bigIntToBuffer(key), 32) + const keyBuf = setLengthLeft(bigIntToBytes(key), 32) // NOTE: this should be the shortest representation let value if (val === BigInt(0)) { - value = Buffer.from([]) + value = Uint8Array.from([]) } else { - value = bigIntToBuffer(val) + value = bigIntToBytes(val) } runState.interpreter.transientStorageStore(keyBuf, value) @@ -924,7 +925,7 @@ export const handlers: Map = new Map([ const gasLimit = runState.messageGasLimit! runState.messageGasLimit = undefined - let data = Buffer.alloc(0) + let data = new Uint8Array(0) if (length !== BigInt(0)) { data = runState.memory.read(Number(offset), Number(length), true) } @@ -954,7 +955,7 @@ export const handlers: Map = new Map([ const gasLimit = runState.messageGasLimit! runState.messageGasLimit = undefined - let data = Buffer.alloc(0) + let data = new Uint8Array(0) if (length !== BigInt(0)) { data = runState.memory.read(Number(offset), Number(length), true) } @@ -963,7 +964,7 @@ export const handlers: Map = new Map([ gasLimit, value, data, - setLengthLeft(bigIntToBuffer(salt), 32) + setLengthLeft(bigIntToBytes(salt), 32) ) runState.stack.push(ret) }, @@ -974,9 +975,9 @@ export const handlers: Map = new Map([ async function (runState: RunState) { const [_currentGasLimit, toAddr, value, inOffset, inLength, outOffset, outLength] = runState.stack.popN(7) - const toAddress = new Address(addressToBuffer(toAddr)) + const toAddress = new Address(addresstoBytes(toAddr)) - let data = Buffer.alloc(0) + let data = new Uint8Array(0) if (inLength !== BigInt(0)) { data = runState.memory.read(Number(inOffset), Number(inLength), true) } @@ -996,12 +997,12 @@ export const handlers: Map = new Map([ async function (runState: RunState) { const [_currentGasLimit, toAddr, value, inOffset, inLength, outOffset, outLength] = runState.stack.popN(7) - const toAddress = new Address(addressToBuffer(toAddr)) + const toAddress = new Address(addresstoBytes(toAddr)) const gasLimit = runState.messageGasLimit! runState.messageGasLimit = undefined - let data = Buffer.alloc(0) + let data = new Uint8Array(0) if (inLength !== BigInt(0)) { data = runState.memory.read(Number(inOffset), Number(inLength), true) } @@ -1019,9 +1020,9 @@ export const handlers: Map = new Map([ const value = runState.interpreter.getCallValue() const [_currentGasLimit, toAddr, inOffset, inLength, outOffset, outLength] = runState.stack.popN(6) - const toAddress = new Address(addressToBuffer(toAddr)) + const toAddress = new Address(addresstoBytes(toAddr)) - let data = Buffer.alloc(0) + let data = new Uint8Array(0) if (inLength !== BigInt(0)) { data = runState.memory.read(Number(inOffset), Number(inLength), true) } @@ -1052,18 +1053,18 @@ export const handlers: Map = new Map([ } const yParity = BigInt(mem[31]) - const r = mem.slice(32, 64) - const s = mem.slice(64, 96) - const commit = mem.slice(96, 128) + const r = mem.subarray(32, 64) + const s = mem.subarray(64, 96) + const commit = mem.subarray(96, 128) - if (bufferToBigInt(s) > SECP256K1_ORDER_DIV_2) { + if (bytesToBigInt(s) > SECP256K1_ORDER_DIV_2) { trap(ERROR.AUTH_INVALID_S) } - const paddedInvokerAddress = setLengthLeft(runState.interpreter._env.address.buf, 32) - const chainId = setLengthLeft(bigIntToBuffer(runState.interpreter.getChainId()), 32) - const message = Buffer.concat([EIP3074MAGIC, chainId, paddedInvokerAddress, commit]) - const msgHash = Buffer.from(keccak256(message)) + const paddedInvokerAddress = setLengthLeft(runState.interpreter._env.address.bytes, 32) + const chainId = setLengthLeft(bigIntToBytes(runState.interpreter.getChainId()), 32) + const message = concatBytesNoTypeCheck(EIP3074MAGIC, chainId, paddedInvokerAddress, commit) + const msgHash = keccak256(message) let recover try { @@ -1079,7 +1080,7 @@ export const handlers: Map = new Map([ const address = new Address(addressBuffer) runState.auth = address - const expectedAddress = new Address(setLengthLeft(bigIntToBuffer(authority), 20)) + const expectedAddress = new Address(setLengthLeft(bigIntToBytes(authority), 20)) if (!expectedAddress.equals(address)) { // expected address does not equal the recovered address, clear auth variable @@ -1107,12 +1108,12 @@ export const handlers: Map = new Map([ retLength, ] = runState.stack.popN(8) - const toAddress = new Address(addressToBuffer(addr)) + const toAddress = new Address(addresstoBytes(addr)) const gasLimit = runState.messageGasLimit! runState.messageGasLimit = undefined - let data = Buffer.alloc(0) + let data = new Uint8Array(0) if (argsLength !== BigInt(0)) { data = runState.memory.read(Number(argsOffset), Number(argsLength)) } @@ -1130,12 +1131,12 @@ export const handlers: Map = new Map([ const value = BigInt(0) const [_currentGasLimit, toAddr, inOffset, inLength, outOffset, outLength] = runState.stack.popN(6) - const toAddress = new Address(addressToBuffer(toAddr)) + const toAddress = new Address(addresstoBytes(toAddr)) const gasLimit = runState.messageGasLimit! runState.messageGasLimit = undefined - let data = Buffer.alloc(0) + let data = new Uint8Array(0) if (inLength !== BigInt(0)) { data = runState.memory.read(Number(inOffset), Number(inLength), true) } @@ -1151,7 +1152,7 @@ export const handlers: Map = new Map([ 0xf3, function (runState) { const [offset, length] = runState.stack.popN(2) - let returnData = Buffer.alloc(0) + let returnData = new Uint8Array(0) if (length !== BigInt(0)) { returnData = runState.memory.read(Number(offset), Number(length)) } @@ -1163,7 +1164,7 @@ export const handlers: Map = new Map([ 0xfd, function (runState) { const [offset, length] = runState.stack.popN(2) - let returnData = Buffer.alloc(0) + let returnData = new Uint8Array(0) if (length !== BigInt(0)) { returnData = runState.memory.read(Number(offset), Number(length)) } @@ -1176,7 +1177,7 @@ export const handlers: Map = new Map([ 0xff, async function (runState) { const selfdestructToAddressBigInt = runState.stack.pop() - const selfdestructToAddress = new Address(addressToBuffer(selfdestructToAddressBigInt)) + const selfdestructToAddress = new Address(addresstoBytes(selfdestructToAddressBigInt)) return runState.interpreter.selfDestruct(selfdestructToAddress) }, ], diff --git a/packages/evm/src/opcodes/gas.ts b/packages/evm/src/opcodes/gas.ts index 321bb76853..3b10ea773d 100644 --- a/packages/evm/src/opcodes/gas.ts +++ b/packages/evm/src/opcodes/gas.ts @@ -1,5 +1,5 @@ import { Hardfork } from '@ethereumjs/common' -import { Address, bigIntToBuffer, setLengthLeft } from '@ethereumjs/util' +import { Address, bigIntToBytes, setLengthLeft } from '@ethereumjs/util' import { ERROR } from '../exceptions' @@ -7,7 +7,7 @@ import { updateSstoreGasEIP1283 } from './EIP1283' import { updateSstoreGasEIP2200 } from './EIP2200' import { accessAddressEIP2929, accessStorageEIP2929 } from './EIP2929' import { - addressToBuffer, + addresstoBytes, divCeil, maxCallGas, setLengthLeftStorage, @@ -74,7 +74,7 @@ export const dynamicGasHandlers: Map { if (common.isActivatedEIP(2929) === true) { const addressBigInt = runState.stack.peek()[0] - const address = new Address(addressToBuffer(addressBigInt)) + const address = new Address(addresstoBytes(addressBigInt)) gas += accessAddressEIP2929(runState, address, common) } return gas @@ -112,7 +112,7 @@ export const dynamicGasHandlers: Map { if (common.isActivatedEIP(2929) === true) { const addressBigInt = runState.stack.peek()[0] - const address = new Address(addressToBuffer(addressBigInt)) + const address = new Address(addresstoBytes(addressBigInt)) gas += accessAddressEIP2929(runState, address, common) } return gas @@ -127,7 +127,7 @@ export const dynamicGasHandlers: Map { if (common.isActivatedEIP(2929) === true) { const addressBigInt = runState.stack.peek()[0] - const address = new Address(addressToBuffer(addressBigInt)) + const address = new Address(addresstoBytes(addressBigInt)) gas += accessAddressEIP2929(runState, address, common) } return gas @@ -199,7 +199,7 @@ export const dynamicGasHandlers: Map { const key = runState.stack.peek()[0] - const keyBuf = setLengthLeft(bigIntToBuffer(key), 32) + const keyBuf = setLengthLeft(bigIntToBytes(key), 32) if (common.isActivatedEIP(2929) === true) { gas += accessStorageEIP2929(runState, keyBuf, false, common) @@ -216,18 +216,20 @@ export const dynamicGasHandlers: Map { const [currentGasLimit, toAddr, value, inOffset, inLength, outOffset, outLength] = runState.stack.peek(7) - const toAddress = new Address(addressToBuffer(toAddr)) + const toAddress = new Address(addresstoBytes(toAddr)) if (runState.interpreter.isStatic() && value !== BigInt(0)) { trap(ERROR.STATIC_STATE_CHANGE) @@ -379,7 +381,7 @@ export const dynamicGasHandlers: Map len) { offset = len @@ -84,7 +84,7 @@ export function getDataSlice(data: Buffer, offset: bigint, length: bigint): Buff end = len } - data = data.slice(Number(offset), Number(end)) + data = data.subarray(Number(offset), Number(end)) // Right-pad with zeros to fill dataLength bytes data = setLengthRight(data, Number(length)) @@ -201,8 +201,8 @@ export function writeCallOutput(runState: RunState, outOffset: bigint, outLength */ export function updateSstoreGas( runState: RunState, - currentStorage: Buffer, - value: Buffer, + currentStorage: Uint8Array, + value: Uint8Array, common: Common ): bigint { if ( diff --git a/packages/evm/src/precompiles/01-ecrecover.ts b/packages/evm/src/precompiles/01-ecrecover.ts index a886bc3148..0d48b11901 100644 --- a/packages/evm/src/precompiles/01-ecrecover.ts +++ b/packages/evm/src/precompiles/01-ecrecover.ts @@ -1,5 +1,7 @@ import { - bufferToBigInt, + bytesToBigInt, + bytesToHex, + bytesToPrefixedHexString, ecrecover, publicToAddress, setLengthLeft, @@ -14,7 +16,7 @@ import type { PrecompileInput } from './types' export function precompile01(opts: PrecompileInput): ExecResult { const gasUsed = opts._common.param('gasPrices', 'ecRecover') - if (opts._debug) { + if (opts._debug !== undefined) { opts._debug( `Run ECRECOVER (0x01) precompile data=${short(opts.data)} length=${ opts.data.length @@ -23,7 +25,7 @@ export function precompile01(opts: PrecompileInput): ExecResult { } if (opts.gasLimit < gasUsed) { - if (opts._debug) { + if (opts._debug !== undefined) { opts._debug(`ECRECOVER (0x01) failed: OOG`) } return OOGResult(opts.gasLimit) @@ -31,48 +33,48 @@ export function precompile01(opts: PrecompileInput): ExecResult { const data = setLengthRight(opts.data, 128) - const msgHash = data.slice(0, 32) - const v = data.slice(32, 64) - const vBigInt = bufferToBigInt(v) + const msgHash = data.subarray(0, 32) + const v = data.subarray(32, 64) + const vBigInt = bytesToBigInt(v) // Guard against util's `ecrecover`: without providing chainId this will return // a signature in most of the cases in the cases that `v=0` or `v=1` // However, this should throw, only 27 and 28 is allowed as input if (vBigInt !== BigInt(27) && vBigInt !== BigInt(28)) { - if (opts._debug) { + if (opts._debug !== undefined) { opts._debug(`ECRECOVER (0x01) failed: v neither 27 nor 28`) } return { executionGasUsed: gasUsed, - returnValue: Buffer.alloc(0), + returnValue: new Uint8Array(), } } - const r = data.slice(64, 96) - const s = data.slice(96, 128) + const r = data.subarray(64, 96) + const s = data.subarray(96, 128) let publicKey try { - if (opts._debug) { + if (opts._debug !== undefined) { opts._debug( - `ECRECOVER (0x01): PK recovery with msgHash=${msgHash.toString('hex')} v=${v.toString( - 'hex' - )} r=${r.toString('hex')}s=${s.toString('hex')}}` + `ECRECOVER (0x01): PK recovery with msgHash=${bytesToHex(msgHash)} v=${bytesToHex( + v + )} r=${bytesToHex(r)}s=${bytesToHex(s)}}` ) } - publicKey = ecrecover(msgHash, bufferToBigInt(v), r, s) + publicKey = ecrecover(msgHash, bytesToBigInt(v), r, s) } catch (e: any) { - if (opts._debug) { + if (opts._debug !== undefined) { opts._debug(`ECRECOVER (0x01) failed: PK recovery failed`) } return { executionGasUsed: gasUsed, - returnValue: Buffer.alloc(0), + returnValue: new Uint8Array(0), } } const address = setLengthLeft(publicToAddress(publicKey), 32) - if (opts._debug) { - opts._debug(`ECRECOVER (0x01) return address=${address.toString('hex')}`) + if (opts._debug !== undefined) { + opts._debug(`ECRECOVER (0x01) return address=${bytesToPrefixedHexString(address)}`) } return { executionGasUsed: gasUsed, diff --git a/packages/evm/src/precompiles/02-sha256.ts b/packages/evm/src/precompiles/02-sha256.ts index 7e74dfa03e..7e62b82511 100644 --- a/packages/evm/src/precompiles/02-sha256.ts +++ b/packages/evm/src/precompiles/02-sha256.ts @@ -1,4 +1,4 @@ -import { short, toBuffer } from '@ethereumjs/util' +import { bytesToHex, short } from '@ethereumjs/util' import { sha256 } from 'ethereum-cryptography/sha256' import { OOGResult } from '../evm' @@ -12,7 +12,7 @@ export function precompile02(opts: PrecompileInput): ExecResult { let gasUsed = opts._common.param('gasPrices', 'sha256') gasUsed += opts._common.param('gasPrices', 'sha256Word') * BigInt(Math.ceil(data.length / 32)) - if (opts._debug) { + if (opts._debug !== undefined) { opts._debug( `Run KECCAK256 (0x02) precompile data=${short(opts.data)} length=${ opts.data.length @@ -21,19 +21,19 @@ export function precompile02(opts: PrecompileInput): ExecResult { } if (opts.gasLimit < gasUsed) { - if (opts._debug) { + if (opts._debug !== undefined) { opts._debug(`KECCAK256 (0x02) failed: OOG`) } return OOGResult(opts.gasLimit) } - const hash = toBuffer(sha256(data)) - if (opts._debug) { - opts._debug(`KECCAK256 (0x02) return hash=${hash.toString('hex')}`) + const hash = sha256(data) + if (opts._debug !== undefined) { + opts._debug(`KECCAK256 (0x02) return hash=${bytesToHex(hash)}`) } return { executionGasUsed: gasUsed, - returnValue: hash, + returnValue: sha256(data), } } diff --git a/packages/evm/src/precompiles/03-ripemd160.ts b/packages/evm/src/precompiles/03-ripemd160.ts index 88d6baad51..79ed9e9130 100644 --- a/packages/evm/src/precompiles/03-ripemd160.ts +++ b/packages/evm/src/precompiles/03-ripemd160.ts @@ -1,4 +1,4 @@ -import { setLengthLeft, short, toBuffer } from '@ethereumjs/util' +import { bytesToHex, setLengthLeft, short } from '@ethereumjs/util' import { ripemd160 } from 'ethereum-cryptography/ripemd160' import { OOGResult } from '../evm' @@ -12,7 +12,7 @@ export function precompile03(opts: PrecompileInput): ExecResult { let gasUsed = opts._common.param('gasPrices', 'ripemd160') gasUsed += opts._common.param('gasPrices', 'ripemd160Word') * BigInt(Math.ceil(data.length / 32)) - if (opts._debug) { + if (opts._debug !== undefined) { opts._debug( `Run RIPEMD160 (0x03) precompile data=${short(opts.data)} length=${ opts.data.length @@ -21,19 +21,19 @@ export function precompile03(opts: PrecompileInput): ExecResult { } if (opts.gasLimit < gasUsed) { - if (opts._debug) { + if (opts._debug !== undefined) { opts._debug(`RIPEMD160 (0x03) failed: OOG`) } return OOGResult(opts.gasLimit) } - const hash = setLengthLeft(toBuffer(ripemd160(data)), 32) - if (opts._debug) { - opts._debug(`RIPEMD160 (0x03) return hash=${hash.toString('hex')}`) + const hash = setLengthLeft(ripemd160(data), 32) + if (opts._debug !== undefined) { + opts._debug(`RIPEMD160 (0x03) return hash=${bytesToHex(hash)}`) } return { executionGasUsed: gasUsed, - returnValue: hash, + returnValue: setLengthLeft(ripemd160(data), 32), } } diff --git a/packages/evm/src/precompiles/04-identity.ts b/packages/evm/src/precompiles/04-identity.ts index eddfb3c953..0e50083c95 100644 --- a/packages/evm/src/precompiles/04-identity.ts +++ b/packages/evm/src/precompiles/04-identity.ts @@ -10,7 +10,7 @@ export function precompile04(opts: PrecompileInput): ExecResult { let gasUsed = opts._common.param('gasPrices', 'identity') gasUsed += opts._common.param('gasPrices', 'identityWord') * BigInt(Math.ceil(data.length / 32)) - if (opts._debug) { + if (opts._debug !== undefined) { opts._debug( `Run IDENTITY (0x04) precompile data=${short(opts.data)} length=${ opts.data.length @@ -19,18 +19,18 @@ export function precompile04(opts: PrecompileInput): ExecResult { } if (opts.gasLimit < gasUsed) { - if (opts._debug) { + if (opts._debug !== undefined) { opts._debug(`IDENTITY (0x04) failed: OOG`) } return OOGResult(opts.gasLimit) } - if (opts._debug) { + if (opts._debug !== undefined) { opts._debug(`IDENTITY (0x04) return data=${short(opts.data)}`) } return { executionGasUsed: gasUsed, - returnValue: Buffer.from(data), // Copy the memory (`Buffer.from()`) + returnValue: Uint8Array.from(data), // Copy the memory (`Uint8Array.from()`) } } diff --git a/packages/evm/src/precompiles/05-modexp.ts b/packages/evm/src/precompiles/05-modexp.ts index 70d8cd0bbd..9398e98f1f 100644 --- a/packages/evm/src/precompiles/05-modexp.ts +++ b/packages/evm/src/precompiles/05-modexp.ts @@ -1,6 +1,7 @@ import { - bigIntToBuffer, - bufferToBigInt, + bigIntToBytes, + bytesToBigInt, + bytesToHex, setLengthLeft, setLengthRight, short, @@ -34,18 +35,18 @@ function multComplexityEIP2565(x: bigint): bigint { return words * words } -function getAdjustedExponentLength(data: Buffer): bigint { +function getAdjustedExponentLength(data: Uint8Array): bigint { let expBytesStart try { - const baseLen = bufferToBigInt(data.slice(0, 32)) + const baseLen = bytesToBigInt(data.subarray(0, 32)) expBytesStart = 96 + Number(baseLen) // 96 for base length, then exponent length, and modulus length, then baseLen for the base data, then exponent bytes start } catch (e: any) { expBytesStart = Number.MAX_SAFE_INTEGER - 32 } - const expLen = bufferToBigInt(data.slice(32, 64)) - let firstExpBytes = Buffer.from(data.slice(expBytesStart, expBytesStart + 32)) // first word of the exponent data + const expLen = bytesToBigInt(data.subarray(32, 64)) + let firstExpBytes = data.subarray(expBytesStart, expBytesStart + 32) // first word of the exponent data firstExpBytes = setLengthRight(firstExpBytes, 32) // reading past the data reads virtual zeros - let firstExpBigInt = bufferToBigInt(firstExpBytes) + let firstExpBigInt = bytesToBigInt(firstExpBytes) let max32expLen = 0 if (expLen < BigInt(32)) { max32expLen = 32 - Number(expLen) @@ -90,9 +91,9 @@ export function precompile05(opts: PrecompileInput): ExecResult { adjustedELen = BigInt(1) } - const bLen = bufferToBigInt(data.slice(0, 32)) - const eLen = bufferToBigInt(data.slice(32, 64)) - const mLen = bufferToBigInt(data.slice(64, 96)) + const bLen = bytesToBigInt(data.subarray(0, 32)) + const eLen = bytesToBigInt(data.subarray(32, 64)) + const mLen = bytesToBigInt(data.subarray(64, 96)) let maxLen = bLen if (maxLen < mLen) { @@ -116,7 +117,7 @@ export function precompile05(opts: PrecompileInput): ExecResult { gasUsed = BigInt(200) } } - if (opts._debug) { + if (opts._debug !== undefined) { opts._debug( `Run MODEXP (0x05) precompile data=${short(opts.data)} length=${opts.data.length} gasLimit=${ opts.gasLimit @@ -125,7 +126,7 @@ export function precompile05(opts: PrecompileInput): ExecResult { } if (opts.gasLimit < gasUsed) { - if (opts._debug) { + if (opts._debug !== undefined) { opts._debug(`MODEXP (0x05) failed: OOG`) } return OOGResult(opts.gasLimit) @@ -134,14 +135,14 @@ export function precompile05(opts: PrecompileInput): ExecResult { if (bLen === BigInt(0)) { return { executionGasUsed: gasUsed, - returnValue: setLengthLeft(bigIntToBuffer(BigInt(0)), Number(mLen)), + returnValue: setLengthLeft(bigIntToBytes(BigInt(0)), Number(mLen)), } } if (mLen === BigInt(0)) { return { executionGasUsed: gasUsed, - returnValue: Buffer.alloc(0), + returnValue: new Uint8Array(0), } } @@ -149,18 +150,18 @@ export function precompile05(opts: PrecompileInput): ExecResult { const maxSize = BigInt(2147483647) // @ethereumjs/util setLengthRight limitation if (bLen > maxSize || eLen > maxSize || mLen > maxSize) { - if (opts._debug) { + if (opts._debug !== undefined) { opts._debug(`MODEXP (0x05) failed: OOG`) } return OOGResult(opts.gasLimit) } - const B = bufferToBigInt(setLengthRight(data.slice(Number(bStart), Number(bEnd)), Number(bLen))) - const E = bufferToBigInt(setLengthRight(data.slice(Number(eStart), Number(eEnd)), Number(eLen))) - const M = bufferToBigInt(setLengthRight(data.slice(Number(mStart), Number(mEnd)), Number(mLen))) + const B = bytesToBigInt(setLengthRight(data.subarray(Number(bStart), Number(bEnd)), Number(bLen))) + const E = bytesToBigInt(setLengthRight(data.subarray(Number(eStart), Number(eEnd)), Number(eLen))) + const M = bytesToBigInt(setLengthRight(data.subarray(Number(mStart), Number(mEnd)), Number(mLen))) if (mEnd > maxInt) { - if (opts._debug) { + if (opts._debug !== undefined) { opts._debug(`MODEXP (0x05) failed: OOG`) } return OOGResult(opts.gasLimit) @@ -173,13 +174,13 @@ export function precompile05(opts: PrecompileInput): ExecResult { R = expmod(B, E, M) } - const res = setLengthLeft(bigIntToBuffer(R), Number(mLen)) - if (opts._debug) { - opts._debug(`MODEXP (0x05) return value=${res.toString('hex')}`) + const res = setLengthLeft(bigIntToBytes(R), Number(mLen)) + if (opts._debug !== undefined) { + opts._debug(`MODEXP (0x05) return value=${bytesToHex(res)}`) } return { executionGasUsed: gasUsed, - returnValue: res, + returnValue: setLengthLeft(bigIntToBytes(R), Number(mLen)), } } diff --git a/packages/evm/src/precompiles/06-ecadd.ts b/packages/evm/src/precompiles/06-ecadd.ts index 5bd67a3991..aee4b5efb1 100644 --- a/packages/evm/src/precompiles/06-ecadd.ts +++ b/packages/evm/src/precompiles/06-ecadd.ts @@ -1,4 +1,5 @@ import { short } from '@ethereumjs/util' +import { bytesToHex, hexToBytes } from 'ethereum-cryptography/utils' import { OOGResult } from '../evm' @@ -8,10 +9,10 @@ import type { PrecompileInput } from './types' const bn128 = require('rustbn.js') export function precompile06(opts: PrecompileInput): ExecResult { - const inputData = opts.data.slice(0, 128) + const inputData = bytesToHex(opts.data.subarray(0, 128)) const gasUsed = opts._common.param('gasPrices', 'ecAdd') - if (opts._debug) { + if (opts._debug !== undefined) { opts._debug( `Run ECADD (0x06) precompile data=${short(opts.data)} length=${opts.data.length} gasLimit=${ opts.gasLimit @@ -19,24 +20,24 @@ export function precompile06(opts: PrecompileInput): ExecResult { ) } if (opts.gasLimit < gasUsed) { - if (opts._debug) { + if (opts._debug !== undefined) { opts._debug(`ECADD (0x06) failed: OOG`) } return OOGResult(opts.gasLimit) } - const returnData: Buffer = bn128.add(inputData) + const returnData = hexToBytes(bn128.add(inputData)) // check ecadd success or failure by comparing the output length if (returnData.length !== 64) { - if (opts._debug) { + if (opts._debug !== undefined) { opts._debug(`ECADD (0x06) failed: OOG`) } return OOGResult(opts.gasLimit) } - if (opts._debug) { - opts._debug(`ECADD (0x06) return value=${returnData.toString('hex')}`) + if (opts._debug !== undefined) { + opts._debug(`ECADD (0x06) return value=${bytesToHex(returnData)}`) } return { diff --git a/packages/evm/src/precompiles/07-ecmul.ts b/packages/evm/src/precompiles/07-ecmul.ts index 7670b3bc11..8591fe3f1f 100644 --- a/packages/evm/src/precompiles/07-ecmul.ts +++ b/packages/evm/src/precompiles/07-ecmul.ts @@ -1,4 +1,5 @@ import { short } from '@ethereumjs/util' +import { bytesToHex, hexToBytes } from 'ethereum-cryptography/utils' import { OOGResult } from '../evm' @@ -8,9 +9,9 @@ import type { PrecompileInput } from './types' const bn128 = require('rustbn.js') export function precompile07(opts: PrecompileInput): ExecResult { - const inputData = opts.data.slice(0, 128) + const inputData = bytesToHex(opts.data.subarray(0, 128)) const gasUsed = opts._common.param('gasPrices', 'ecMul') - if (opts._debug) { + if (opts._debug !== undefined) { opts._debug( `Run ECMUL (0x07) precompile data=${short(opts.data)} length=${opts.data.length} gasLimit=${ opts.gasLimit @@ -19,24 +20,25 @@ export function precompile07(opts: PrecompileInput): ExecResult { } if (opts.gasLimit < gasUsed) { - if (opts._debug) { + if (opts._debug !== undefined) { opts._debug(`ECMUL (0x07) failed: OOG`) } return OOGResult(opts.gasLimit) } - const returnData = bn128.mul(inputData) + const returnData = hexToBytes(bn128.mul(inputData)) + // check ecmul success or failure by comparing the output length if (returnData.length !== 64) { - if (opts._debug) { + if (opts._debug !== undefined) { opts._debug(`ECMUL (0x07) failed: OOG`) } // TODO: should this really return OOG? return OOGResult(opts.gasLimit) } - if (opts._debug) { - opts._debug(`ECMUL (0x07) return value=${returnData.toString('hex')}`) + if (opts._debug !== undefined) { + opts._debug(`ECMUL (0x07) return value=${bytesToHex(returnData)}`) } return { diff --git a/packages/evm/src/precompiles/08-ecpairing.ts b/packages/evm/src/precompiles/08-ecpairing.ts index ac45df8b0f..9f9d16793f 100644 --- a/packages/evm/src/precompiles/08-ecpairing.ts +++ b/packages/evm/src/precompiles/08-ecpairing.ts @@ -1,4 +1,5 @@ import { short } from '@ethereumjs/util' +import { bytesToHex, hexToBytes } from 'ethereum-cryptography/utils' import { OOGResult } from '../evm' @@ -14,7 +15,7 @@ export function precompile08(opts: PrecompileInput): ExecResult { const gasUsed = opts._common.param('gasPrices', 'ecPairing') + inputDataSize * opts._common.param('gasPrices', 'ecPairingWord') - if (opts._debug) { + if (opts._debug !== undefined) { opts._debug( `Run ECPAIRING (0x08) precompile data=${short(opts.data)} length=${ opts.data.length @@ -23,25 +24,25 @@ export function precompile08(opts: PrecompileInput): ExecResult { } if (opts.gasLimit < gasUsed) { - if (opts._debug) { + if (opts._debug !== undefined) { opts._debug(`ECPAIRING (0x08) failed: OOG`) } return OOGResult(opts.gasLimit) } - const returnData = bn128.pairing(inputData) + const returnData = hexToBytes(bn128.pairing(bytesToHex(inputData))) // check ecpairing success or failure by comparing the output length if (returnData.length !== 32) { - if (opts._debug) { + if (opts._debug !== undefined) { opts._debug(`ECPAIRING (0x08) failed: OOG`) } // TODO: should this really return OOG? return OOGResult(opts.gasLimit) } - if (opts._debug) { - opts._debug(`ECPAIRING (0x08) return value=${returnData.toString('hex')}`) + if (opts._debug !== undefined) { + opts._debug(`ECPAIRING (0x08) return value=${bytesToHex(returnData)}`) } return { diff --git a/packages/evm/src/precompiles/09-blake2f.ts b/packages/evm/src/precompiles/09-blake2f.ts index 1dcb4981cb..9556700089 100644 --- a/packages/evm/src/precompiles/09-blake2f.ts +++ b/packages/evm/src/precompiles/09-blake2f.ts @@ -1,4 +1,4 @@ -import { short } from '@ethereumjs/util' +import { bytesToHex, short } from '@ethereumjs/util' import { OOGResult } from '../evm' import { ERROR, EvmError } from '../exceptions' @@ -160,37 +160,37 @@ export function F(h: Uint32Array, m: Uint32Array, t: Uint32Array, f: boolean, ro export function precompile09(opts: PrecompileInput): ExecResult { const data = opts.data if (data.length !== 213) { - if (opts._debug) { + if (opts._debug !== undefined) { opts._debug(`BLAKE2F (0x09) failed: OUT_OF_RANGE dataLength=${data.length}`) } return { - returnValue: Buffer.alloc(0), + returnValue: new Uint8Array(0), executionGasUsed: opts.gasLimit, exceptionError: new EvmError(ERROR.OUT_OF_RANGE), } } - const lastByte = data.slice(212, 213)[0] + const lastByte = data.subarray(212, 213)[0] if (lastByte !== 1 && lastByte !== 0) { - if (opts._debug) { + if (opts._debug !== undefined) { opts._debug(`BLAKE2F (0x09) failed: OUT_OF_RANGE lastByte=${lastByte}`) } return { - returnValue: Buffer.alloc(0), + returnValue: new Uint8Array(0), executionGasUsed: opts.gasLimit, exceptionError: new EvmError(ERROR.OUT_OF_RANGE), } } - const rounds = data.slice(0, 4).readUInt32BE(0) - const hRaw = data.slice(4, 68) - const mRaw = data.slice(68, 196) - const tRaw = data.slice(196, 212) + const rounds = new DataView(data.subarray(0, 4).buffer).getUint32(0) + const hRaw = new DataView(data.buffer, 4, 64) + const mRaw = new DataView(data.buffer, 68, 128) + const tRaw = new DataView(data.buffer, 196, 16) // final const f = lastByte === 1 let gasUsed = opts._common.param('gasPrices', 'blake2Round') gasUsed *= BigInt(rounds) - if (opts._debug) { + if (opts._debug !== undefined) { opts._debug( `Run BLAKE2F (0x09) precompile data=${short(opts.data)} length=${opts.data.length} gasLimit=${ opts.gasLimit @@ -199,7 +199,7 @@ export function precompile09(opts: PrecompileInput): ExecResult { } if (opts.gasLimit < gasUsed) { - if (opts._debug) { + if (opts._debug !== undefined) { opts._debug(`BLAKE2F (0x09) failed: OOG`) } return OOGResult(opts.gasLimit) @@ -207,28 +207,29 @@ export function precompile09(opts: PrecompileInput): ExecResult { const h = new Uint32Array(16) for (let i = 0; i < 16; i++) { - h[i] = hRaw.readUInt32LE(i * 4) + h[i] = hRaw.getUint32(i * 4, true) } const m = new Uint32Array(32) for (let i = 0; i < 32; i++) { - m[i] = mRaw.readUInt32LE(i * 4) + m[i] = mRaw.getUint32(i * 4, true) } const t = new Uint32Array(4) for (let i = 0; i < 4; i++) { - t[i] = tRaw.readUInt32LE(i * 4) + t[i] = tRaw.getUint32(i * 4, true) } F(h, m, t, f, rounds) - const output = Buffer.alloc(64) + const output = new Uint8Array(64) + const outputView = new DataView(output.buffer) for (let i = 0; i < 16; i++) { - output.writeUInt32LE(h[i], i * 4) + outputView.setUint32(i * 4, h[i], true) } - if (opts._debug) { - opts._debug(`BLAKE2F (0x09) return hash=${output.toString('hex')}`) + if (opts._debug !== undefined) { + opts._debug(`BLAKE2F (0x09) return hash=${bytesToHex(output)}`) } return { diff --git a/packages/evm/src/precompiles/0a-bls12-g1add.ts b/packages/evm/src/precompiles/0a-bls12-g1add.ts index aa3853eaba..edbd32748c 100644 --- a/packages/evm/src/precompiles/0a-bls12-g1add.ts +++ b/packages/evm/src/precompiles/0a-bls12-g1add.ts @@ -1,4 +1,5 @@ import { short } from '@ethereumjs/util' +import { equalsBytes } from 'ethereum-cryptography/utils' import { EvmErrorResult, OOGResult } from '../evm' import { ERROR, EvmError } from '../exceptions' @@ -15,7 +16,7 @@ export async function precompile0a(opts: PrecompileInput): Promise { // note: the gas used is constant; even if the input is incorrect. const gasUsed = opts._common.paramByEIP('gasPrices', 'Bls12381G1AddGas', 2537) ?? BigInt(0) - if (opts._debug) { + if (opts._debug !== undefined) { opts._debug( `Run BLS12G1ADD (0x0a) precompile data=${short(opts.data)} length=${ opts.data.length @@ -24,21 +25,21 @@ export async function precompile0a(opts: PrecompileInput): Promise { } if (opts.gasLimit < gasUsed) { - if (opts._debug) { + if (opts._debug !== undefined) { opts._debug(`BLS12G1ADD (0x0a) failed: OOG`) } return OOGResult(opts.gasLimit) } if (inputData.length !== 256) { - if (opts._debug) { + if (opts._debug !== undefined) { opts._debug(`BLS12G1ADD (0x0a) failed: Invalid input length length=${inputData.length}`) } return EvmErrorResult(new EvmError(ERROR.BLS_12_381_INVALID_INPUT_LENGTH), opts.gasLimit) } // check if some parts of input are zero bytes. - const zeroBytes16 = Buffer.alloc(16, 0) + const zeroBytes16 = new Uint8Array(16) const zeroByteCheck = [ [0, 16], [64, 80], @@ -47,9 +48,9 @@ export async function precompile0a(opts: PrecompileInput): Promise { ] for (const index in zeroByteCheck) { - const slicedBuffer = opts.data.slice(zeroByteCheck[index][0], zeroByteCheck[index][1]) - if (!slicedBuffer.equals(zeroBytes16)) { - if (opts._debug) { + const slicedBuffer = opts.data.subarray(zeroByteCheck[index][0], zeroByteCheck[index][1]) + if (!(equalsBytes(slicedBuffer, zeroBytes16) === true)) { + if (opts._debug !== undefined) { opts._debug(`BLS12G1ADD (0x0a) failed: Point not on curve`) } return EvmErrorResult(new EvmError(ERROR.BLS_12_381_POINT_NOT_ON_CURVE), opts.gasLimit) @@ -60,10 +61,10 @@ export async function precompile0a(opts: PrecompileInput): Promise { let mclPoint1 let mclPoint2 try { - mclPoint1 = BLS12_381_ToG1Point(opts.data.slice(0, 128), mcl) - mclPoint2 = BLS12_381_ToG1Point(opts.data.slice(128, 256), mcl) + mclPoint1 = BLS12_381_ToG1Point(opts.data.subarray(0, 128), mcl) + mclPoint2 = BLS12_381_ToG1Point(opts.data.subarray(128, 256), mcl) } catch (e: any) { - if (opts._debug) { + if (opts._debug !== undefined) { opts._debug(`BLS12G1ADD (0x0a) failed: ${e.message}`) } return EvmErrorResult(e, opts.gasLimit) @@ -73,7 +74,7 @@ export async function precompile0a(opts: PrecompileInput): Promise { const returnValue = BLS12_381_FromG1Point(result) - if (opts._debug) { + if (opts._debug !== undefined) { opts._debug(`BLS12G1ADD (0x0a) return value=${returnValue.toString('hex')}`) } diff --git a/packages/evm/src/precompiles/0b-bls12-g1mul.ts b/packages/evm/src/precompiles/0b-bls12-g1mul.ts index 704255835a..b6253c48da 100644 --- a/packages/evm/src/precompiles/0b-bls12-g1mul.ts +++ b/packages/evm/src/precompiles/0b-bls12-g1mul.ts @@ -1,4 +1,5 @@ import { short } from '@ethereumjs/util' +import { equalsBytes } from 'ethereum-cryptography/utils' import { EvmErrorResult, OOGResult } from '../evm' import { ERROR, EvmError } from '../exceptions' @@ -19,7 +20,7 @@ export async function precompile0b(opts: PrecompileInput): Promise { // note: the gas used is constant; even if the input is incorrect. const gasUsed = opts._common.paramByEIP('gasPrices', 'Bls12381G1MulGas', 2537) ?? BigInt(0) - if (opts._debug) { + if (opts._debug !== undefined) { opts._debug( `Run BLS12G1MUL (0x0b) precompile data=${short(opts.data)} length=${ opts.data.length @@ -28,30 +29,30 @@ export async function precompile0b(opts: PrecompileInput): Promise { } if (opts.gasLimit < gasUsed) { - if (opts._debug) { + if (opts._debug !== undefined) { opts._debug(`BLS12G1MUL (0x0b) failed: OOG`) } return OOGResult(opts.gasLimit) } if (inputData.length !== 160) { - if (opts._debug) { + if (opts._debug !== undefined) { opts._debug(`BLS12G1MUL (0x0b) failed: Invalid input length length=${inputData.length}`) } return EvmErrorResult(new EvmError(ERROR.BLS_12_381_INVALID_INPUT_LENGTH), opts.gasLimit) } // check if some parts of input are zero bytes. - const zeroBytes16 = Buffer.alloc(16, 0) + const zeroBytes16 = new Uint8Array(16) const zeroByteCheck = [ [0, 16], [64, 80], ] for (const index in zeroByteCheck) { - const slicedBuffer = opts.data.slice(zeroByteCheck[index][0], zeroByteCheck[index][1]) - if (!slicedBuffer.equals(zeroBytes16)) { - if (opts._debug) { + const slicedBuffer = opts.data.subarray(zeroByteCheck[index][0], zeroByteCheck[index][1]) + if (!equalsBytes(slicedBuffer, zeroBytes16)) { + if (opts._debug !== undefined) { opts._debug(`BLS12G1MUL (0x0b) failed: Point not on curve`) } return EvmErrorResult(new EvmError(ERROR.BLS_12_381_POINT_NOT_ON_CURVE), opts.gasLimit) @@ -62,21 +63,21 @@ export async function precompile0b(opts: PrecompileInput): Promise { let mclPoint try { - mclPoint = BLS12_381_ToG1Point(opts.data.slice(0, 128), mcl) + mclPoint = BLS12_381_ToG1Point(opts.data.subarray(0, 128), mcl) } catch (e: any) { - if (opts._debug) { + if (opts._debug !== undefined) { opts._debug(`BLS12G1MUL (0x0b) failed: ${e.message}`) } return EvmErrorResult(e, opts.gasLimit) } - const frPoint = BLS12_381_ToFrPoint(opts.data.slice(128, 160), mcl) + const frPoint = BLS12_381_ToFrPoint(opts.data.subarray(128, 160), mcl) const result = mcl.mul(mclPoint, frPoint) const returnValue = BLS12_381_FromG1Point(result) - if (opts._debug) { + if (opts._debug !== undefined) { opts._debug(`BLS12G1MUL (0x0b) return value=${returnValue.toString('hex')}`) } diff --git a/packages/evm/src/precompiles/0c-bls12-g1multiexp.ts b/packages/evm/src/precompiles/0c-bls12-g1multiexp.ts index cee17ba973..884b23d6a1 100644 --- a/packages/evm/src/precompiles/0c-bls12-g1multiexp.ts +++ b/packages/evm/src/precompiles/0c-bls12-g1multiexp.ts @@ -1,4 +1,5 @@ import { short } from '@ethereumjs/util' +import { equalsBytes } from 'ethereum-cryptography/utils' import { EvmErrorResult, OOGResult } from '../evm' import { ERROR, EvmError } from '../exceptions' @@ -18,7 +19,7 @@ export async function precompile0c(opts: PrecompileInput): Promise { const inputData = opts.data if (inputData.length === 0) { - if (opts._debug) { + if (opts._debug !== undefined) { opts._debug(`BLS12MULTIEXP (0x0c) failed: Empty input`) } return EvmErrorResult(new EvmError(ERROR.BLS_12_381_INPUT_EMPTY), opts.gasLimit) // follow Geths implementation @@ -46,7 +47,7 @@ export async function precompile0c(opts: PrecompileInput): Promise { } const gasUsed = (gasUsedPerPair * BigInt(numPairs) * BigInt(gasDiscountMultiplier)) / BigInt(1000) - if (opts._debug) { + if (opts._debug !== undefined) { opts._debug( `Run BLS12MULTIEXP (0x0c) precompile data=${short(opts.data)} length=${ opts.data.length @@ -55,14 +56,14 @@ export async function precompile0c(opts: PrecompileInput): Promise { } if (opts.gasLimit < gasUsed) { - if (opts._debug) { + if (opts._debug !== undefined) { opts._debug(`BLS12MULTIEXP (0x0c) failed: OOG`) } return OOGResult(opts.gasLimit) } if (inputData.length % 160 !== 0) { - if (opts._debug) { + if (opts._debug !== undefined) { opts._debug(`BLS12MULTIEXP (0x0c) failed: Invalid input length length=${inputData.length}`) } return EvmErrorResult(new EvmError(ERROR.BLS_12_381_INVALID_INPUT_LENGTH), opts.gasLimit) @@ -70,7 +71,7 @@ export async function precompile0c(opts: PrecompileInput): Promise { // prepare pairing list and check for mandatory zero bytes - const zeroBytes16 = Buffer.alloc(16, 0) + const zeroBytes16 = new Uint8Array(16) const zeroByteCheck = [ [0, 16], [64, 80], @@ -83,12 +84,12 @@ export async function precompile0c(opts: PrecompileInput): Promise { // zero bytes check const pairStart = 160 * k for (const index in zeroByteCheck) { - const slicedBuffer = opts.data.slice( + const slicedBuffer = opts.data.subarray( zeroByteCheck[index][0] + pairStart, zeroByteCheck[index][1] + pairStart ) - if (!slicedBuffer.equals(zeroBytes16)) { - if (opts._debug) { + if (!(equalsBytes(slicedBuffer, zeroBytes16) === true)) { + if (opts._debug !== undefined) { opts._debug(`BLS12MULTIEXP (0x0c) failed: Point not on curve`) } return EvmErrorResult(new EvmError(ERROR.BLS_12_381_POINT_NOT_ON_CURVE), opts.gasLimit) @@ -96,14 +97,14 @@ export async function precompile0c(opts: PrecompileInput): Promise { } let G1 try { - G1 = BLS12_381_ToG1Point(opts.data.slice(pairStart, pairStart + 128), mcl) + G1 = BLS12_381_ToG1Point(opts.data.subarray(pairStart, pairStart + 128), mcl) } catch (e: any) { - if (opts._debug) { + if (opts._debug !== undefined) { opts._debug(`BLS12MULTIEXP (0x0c) failed: ${e.message}`) } return EvmErrorResult(e, opts.gasLimit) } - const Fr = BLS12_381_ToFrPoint(opts.data.slice(pairStart + 128, pairStart + 160), mcl) + const Fr = BLS12_381_ToFrPoint(opts.data.subarray(pairStart + 128, pairStart + 160), mcl) G1Array.push(G1) FrArray.push(Fr) @@ -113,7 +114,7 @@ export async function precompile0c(opts: PrecompileInput): Promise { const returnValue = BLS12_381_FromG1Point(result) - if (opts._debug) { + if (opts._debug !== undefined) { opts._debug(`BLS12MULTIEXP (0x0c) return value=${returnValue.toString('hex')}`) } diff --git a/packages/evm/src/precompiles/0d-bls12-g2add.ts b/packages/evm/src/precompiles/0d-bls12-g2add.ts index 963c740c01..3fdb64351c 100644 --- a/packages/evm/src/precompiles/0d-bls12-g2add.ts +++ b/packages/evm/src/precompiles/0d-bls12-g2add.ts @@ -1,4 +1,5 @@ import { short } from '@ethereumjs/util' +import { equalsBytes } from 'ethereum-cryptography/utils' import { EvmErrorResult, OOGResult } from '../evm' import { ERROR, EvmError } from '../exceptions' @@ -15,7 +16,7 @@ export async function precompile0d(opts: PrecompileInput): Promise { // note: the gas used is constant; even if the input is incorrect. const gasUsed = opts._common.paramByEIP('gasPrices', 'Bls12381G2AddGas', 2537) ?? BigInt(0) - if (opts._debug) { + if (opts._debug !== undefined) { opts._debug( `Run BLS12G2ADD (0x0d) precompile data=${short(opts.data)} length=${ opts.data.length @@ -24,21 +25,21 @@ export async function precompile0d(opts: PrecompileInput): Promise { } if (opts.gasLimit < gasUsed) { - if (opts._debug) { + if (opts._debug !== undefined) { opts._debug(`BLS12G2ADD (0x0d) failed: OOG`) } return OOGResult(opts.gasLimit) } if (inputData.length !== 512) { - if (opts._debug) { + if (opts._debug !== undefined) { opts._debug(`BLS12G2ADD (0x0d) failed: Invalid input length length=${inputData.length}`) } return EvmErrorResult(new EvmError(ERROR.BLS_12_381_INVALID_INPUT_LENGTH), opts.gasLimit) } // check if some parts of input are zero bytes. - const zeroBytes16 = Buffer.alloc(16, 0) + const zeroBytes16 = new Uint8Array(16) const zeroByteCheck = [ [0, 16], [64, 80], @@ -51,9 +52,9 @@ export async function precompile0d(opts: PrecompileInput): Promise { ] for (const index in zeroByteCheck) { - const slicedBuffer = opts.data.slice(zeroByteCheck[index][0], zeroByteCheck[index][1]) - if (!slicedBuffer.equals(zeroBytes16)) { - if (opts._debug) { + const slicedBuffer = opts.data.subarray(zeroByteCheck[index][0], zeroByteCheck[index][1]) + if (!(equalsBytes(slicedBuffer, zeroBytes16) === true)) { + if (opts._debug !== undefined) { opts._debug(`BLS12G2ADD (0x0d) failed: Point not on curve`) } return EvmErrorResult(new EvmError(ERROR.BLS_12_381_POINT_NOT_ON_CURVE), opts.gasLimit) @@ -67,8 +68,8 @@ export async function precompile0d(opts: PrecompileInput): Promise { let mclPoint2 try { - mclPoint1 = BLS12_381_ToG2Point(opts.data.slice(0, 256), mcl) - mclPoint2 = BLS12_381_ToG2Point(opts.data.slice(256, 512), mcl) + mclPoint1 = BLS12_381_ToG2Point(opts.data.subarray(0, 256), mcl) + mclPoint2 = BLS12_381_ToG2Point(opts.data.subarray(256, 512), mcl) } catch (e: any) { return EvmErrorResult(e, opts.gasLimit) } @@ -77,7 +78,7 @@ export async function precompile0d(opts: PrecompileInput): Promise { const returnValue = BLS12_381_FromG2Point(result) - if (opts._debug) { + if (opts._debug !== undefined) { opts._debug(`BLS12G2ADD (0x0d) return value=${returnValue.toString('hex')}`) } diff --git a/packages/evm/src/precompiles/0e-bls12-g2mul.ts b/packages/evm/src/precompiles/0e-bls12-g2mul.ts index ca72e35386..1b25251d65 100644 --- a/packages/evm/src/precompiles/0e-bls12-g2mul.ts +++ b/packages/evm/src/precompiles/0e-bls12-g2mul.ts @@ -1,4 +1,5 @@ import { short } from '@ethereumjs/util' +import { equalsBytes } from 'ethereum-cryptography/utils' import { EvmErrorResult, OOGResult } from '../evm' import { ERROR, EvmError } from '../exceptions' @@ -19,7 +20,7 @@ export async function precompile0e(opts: PrecompileInput): Promise { // note: the gas used is constant; even if the input is incorrect. const gasUsed = opts._common.paramByEIP('gasPrices', 'Bls12381G2MulGas', 2537) ?? BigInt(0) - if (opts._debug) { + if (opts._debug !== undefined) { opts._debug( `Run BLS12G2MUL (0x0e) precompile data=${short(opts.data)} length=${ opts.data.length @@ -28,21 +29,21 @@ export async function precompile0e(opts: PrecompileInput): Promise { } if (opts.gasLimit < gasUsed) { - if (opts._debug) { + if (opts._debug !== undefined) { opts._debug(`BLS12G2MUL (0x0e) failed: OOG`) } return OOGResult(opts.gasLimit) } if (inputData.length !== 288) { - if (opts._debug) { + if (opts._debug !== undefined) { opts._debug(`BLS12G2MUL (0x0e) failed: Invalid input length length=${inputData.length}`) } return EvmErrorResult(new EvmError(ERROR.BLS_12_381_INVALID_INPUT_LENGTH), opts.gasLimit) } // check if some parts of input are zero bytes. - const zeroBytes16 = Buffer.alloc(16, 0) + const zeroBytes16 = new Uint8Array(16) const zeroByteCheck = [ [0, 16], [64, 80], @@ -51,9 +52,9 @@ export async function precompile0e(opts: PrecompileInput): Promise { ] for (const index in zeroByteCheck) { - const slicedBuffer = opts.data.slice(zeroByteCheck[index][0], zeroByteCheck[index][1]) - if (!slicedBuffer.equals(zeroBytes16)) { - if (opts._debug) { + const slicedBuffer = opts.data.subarray(zeroByteCheck[index][0], zeroByteCheck[index][1]) + if (!equalsBytes(slicedBuffer, zeroBytes16)) { + if (opts._debug !== undefined) { opts._debug(`BLS12G2MUL (0x0e) failed: Point not on curve`) } return EvmErrorResult(new EvmError(ERROR.BLS_12_381_POINT_NOT_ON_CURVE), opts.gasLimit) @@ -65,21 +66,21 @@ export async function precompile0e(opts: PrecompileInput): Promise { // convert input to mcl G2 point/Fr point, add them, and convert the output to a Buffer. let mclPoint try { - mclPoint = BLS12_381_ToG2Point(opts.data.slice(0, 256), mcl) + mclPoint = BLS12_381_ToG2Point(opts.data.subarray(0, 256), mcl) } catch (e: any) { - if (opts._debug) { + if (opts._debug !== undefined) { opts._debug(`BLS12G2MUL (0x0e) failed: ${e.message}`) } return EvmErrorResult(e, opts.gasLimit) } - const frPoint = BLS12_381_ToFrPoint(opts.data.slice(256, 288), mcl) + const frPoint = BLS12_381_ToFrPoint(opts.data.subarray(256, 288), mcl) const result = mcl.mul(mclPoint, frPoint) const returnValue = BLS12_381_FromG2Point(result) - if (opts._debug) { + if (opts._debug !== undefined) { opts._debug(`BLS12G2MUL (0x0e) return value=${returnValue.toString('hex')}`) } diff --git a/packages/evm/src/precompiles/0f-bls12-g2multiexp.ts b/packages/evm/src/precompiles/0f-bls12-g2multiexp.ts index 791c462d6a..d1f4939f2f 100644 --- a/packages/evm/src/precompiles/0f-bls12-g2multiexp.ts +++ b/packages/evm/src/precompiles/0f-bls12-g2multiexp.ts @@ -1,4 +1,5 @@ import { short } from '@ethereumjs/util' +import { equalsBytes } from 'ethereum-cryptography/utils' import { EvmErrorResult, OOGResult } from '../evm' import { ERROR, EvmError } from '../exceptions' @@ -20,7 +21,7 @@ export async function precompile0f(opts: PrecompileInput): Promise { const inputData = opts.data if (inputData.length === 0) { - if (opts._debug) { + if (opts._debug !== undefined) { opts._debug(`BLS12G2MULTIEXP (0x0f) failed: Empty input`) } return EvmErrorResult(new EvmError(ERROR.BLS_12_381_INPUT_EMPTY), opts.gasLimit) // follow Geths implementation @@ -44,7 +45,7 @@ export async function precompile0f(opts: PrecompileInput): Promise { } const gasUsed = (gasUsedPerPair * BigInt(numPairs) * BigInt(gasDiscountMultiplier)) / BigInt(1000) - if (opts._debug) { + if (opts._debug !== undefined) { opts._debug( `Run BLS12G2MULTIEXP (0x0f) precompile data=${short(opts.data)} length=${ opts.data.length @@ -53,14 +54,14 @@ export async function precompile0f(opts: PrecompileInput): Promise { } if (opts.gasLimit < gasUsed) { - if (opts._debug) { + if (opts._debug !== undefined) { opts._debug(`BLS12G2MULTIEXP (0x0f) failed: OOG`) } return OOGResult(opts.gasLimit) } if (inputData.length % 288 !== 0) { - if (opts._debug) { + if (opts._debug !== undefined) { opts._debug(`BLS12G2MULTIEXP (0x0f) failed: Invalid input length length=${inputData.length}`) } return EvmErrorResult(new EvmError(ERROR.BLS_12_381_INVALID_INPUT_LENGTH), opts.gasLimit) @@ -68,7 +69,7 @@ export async function precompile0f(opts: PrecompileInput): Promise { // prepare pairing list and check for mandatory zero bytes - const zeroBytes16 = Buffer.alloc(16, 0) + const zeroBytes16 = new Uint8Array(16) const zeroByteCheck = [ [0, 16], [64, 80], @@ -83,12 +84,12 @@ export async function precompile0f(opts: PrecompileInput): Promise { // zero bytes check const pairStart = 288 * k for (const index in zeroByteCheck) { - const slicedBuffer = opts.data.slice( + const slicedBuffer = opts.data.subarray( zeroByteCheck[index][0] + pairStart, zeroByteCheck[index][1] + pairStart ) - if (!slicedBuffer.equals(zeroBytes16)) { - if (opts._debug) { + if (!(equalsBytes(slicedBuffer, zeroBytes16) === true)) { + if (opts._debug !== undefined) { opts._debug(`BLS12G2MULTIEXP (0x0f) failed: Point not on curve`) } return EvmErrorResult(new EvmError(ERROR.BLS_12_381_POINT_NOT_ON_CURVE), opts.gasLimit) @@ -96,14 +97,14 @@ export async function precompile0f(opts: PrecompileInput): Promise { } let G2 try { - G2 = BLS12_381_ToG2Point(opts.data.slice(pairStart, pairStart + 256), mcl) + G2 = BLS12_381_ToG2Point(opts.data.subarray(pairStart, pairStart + 256), mcl) } catch (e: any) { - if (opts._debug) { + if (opts._debug !== undefined) { opts._debug(`BLS12G2MULTIEXP (0x0f) failed: ${e.message}`) } return EvmErrorResult(e, opts.gasLimit) } - const Fr = BLS12_381_ToFrPoint(opts.data.slice(pairStart + 256, pairStart + 288), mcl) + const Fr = BLS12_381_ToFrPoint(opts.data.subarray(pairStart + 256, pairStart + 288), mcl) G2Array.push(G2) FrArray.push(Fr) @@ -113,7 +114,7 @@ export async function precompile0f(opts: PrecompileInput): Promise { const returnValue = BLS12_381_FromG2Point(result) - if (opts._debug) { + if (opts._debug !== undefined) { opts._debug(`BLS12G2MULTIEXP (0x0f) return value=${returnValue.toString('hex')}`) } diff --git a/packages/evm/src/precompiles/10-bls12-pairing.ts b/packages/evm/src/precompiles/10-bls12-pairing.ts index 606e0f351f..ac3de1f165 100644 --- a/packages/evm/src/precompiles/10-bls12-pairing.ts +++ b/packages/evm/src/precompiles/10-bls12-pairing.ts @@ -1,4 +1,5 @@ -import { short } from '@ethereumjs/util' +import { concatBytesNoTypeCheck, short } from '@ethereumjs/util' +import { bytesToHex, equalsBytes, hexToBytes } from 'ethereum-cryptography/utils' import { EvmErrorResult, OOGResult } from '../evm' import { ERROR, EvmError } from '../exceptions' @@ -8,8 +9,8 @@ import type { PrecompileInput } from './types' const { BLS12_381_ToG1Point, BLS12_381_ToG2Point } = require('./util/bls12_381') -const zeroBuffer = Buffer.alloc(32, 0) -const oneBuffer = Buffer.concat([Buffer.alloc(31, 0), Buffer.from('01', 'hex')]) +const zeroBuffer = new Uint8Array(32) +const oneBuffer = concatBytesNoTypeCheck(new Uint8Array(31), hexToBytes('01')) export async function precompile10(opts: PrecompileInput): Promise { const mcl = (opts._EVM)._mcl! @@ -19,7 +20,7 @@ export async function precompile10(opts: PrecompileInput): Promise { const baseGas = opts._common.paramByEIP('gasPrices', 'Bls12381PairingBaseGas', 2537) ?? BigInt(0) if (inputData.length === 0) { - if (opts._debug) { + if (opts._debug !== undefined) { opts._debug(`BLS12PAIRING (0x10) failed: Empty input`) } return EvmErrorResult(new EvmError(ERROR.BLS_12_381_INPUT_EMPTY), opts.gasLimit) @@ -29,7 +30,7 @@ export async function precompile10(opts: PrecompileInput): Promise { opts._common.paramByEIP('gasPrices', 'Bls12381PairingPerPairGas', 2537) ?? BigInt(0) const gasUsed = baseGas + gasUsedPerPair * BigInt(Math.floor(inputData.length / 384)) - if (opts._debug) { + if (opts._debug !== undefined) { opts._debug( `Run BLS12PAIRING (0x10) precompile data=${short(opts.data)} length=${ opts.data.length @@ -38,14 +39,14 @@ export async function precompile10(opts: PrecompileInput): Promise { } if (inputData.length % 384 !== 0) { - if (opts._debug) { + if (opts._debug !== undefined) { opts._debug(`BLS12PAIRING (0x10) failed: Invalid input length length=${inputData.length}`) } return EvmErrorResult(new EvmError(ERROR.BLS_12_381_INVALID_INPUT_LENGTH), opts.gasLimit) } if (opts.gasLimit < gasUsed) { - if (opts._debug) { + if (opts._debug !== undefined) { opts._debug(`BLS12PAIRING (0x10) failed: OOG`) } return OOGResult(opts.gasLimit) @@ -55,7 +56,7 @@ export async function precompile10(opts: PrecompileInput): Promise { const pairs = [] - const zeroBytes16 = Buffer.alloc(16, 0) + const zeroBytes16 = new Uint8Array(16) const zeroByteCheck = [ [0, 16], [64, 80], @@ -69,12 +70,12 @@ export async function precompile10(opts: PrecompileInput): Promise { // zero bytes check const pairStart = 384 * k for (const index in zeroByteCheck) { - const slicedBuffer = opts.data.slice( + const slicedBuffer = opts.data.subarray( zeroByteCheck[index][0] + pairStart, zeroByteCheck[index][1] + pairStart ) - if (!slicedBuffer.equals(zeroBytes16)) { - if (opts._debug) { + if (!equalsBytes(slicedBuffer, zeroBytes16)) { + if (opts._debug !== undefined) { opts._debug(`BLS12PAIRING (0x10) failed: Point not on curve`) } return EvmErrorResult(new EvmError(ERROR.BLS_12_381_POINT_NOT_ON_CURVE), opts.gasLimit) @@ -82,9 +83,9 @@ export async function precompile10(opts: PrecompileInput): Promise { } let G1 try { - G1 = BLS12_381_ToG1Point(opts.data.slice(pairStart, pairStart + 128), mcl) + G1 = BLS12_381_ToG1Point(opts.data.subarray(pairStart, pairStart + 128), mcl) } catch (e: any) { - if (opts._debug) { + if (opts._debug !== undefined) { opts._debug(`BLS12PAIRING (0x10) failed: ${e.message}`) } return EvmErrorResult(e, opts.gasLimit) @@ -93,9 +94,9 @@ export async function precompile10(opts: PrecompileInput): Promise { const g2start = pairStart + 128 let G2 try { - G2 = BLS12_381_ToG2Point(opts.data.slice(g2start, g2start + 256), mcl) + G2 = BLS12_381_ToG2Point(opts.data.subarray(g2start, g2start + 256), mcl) } catch (e: any) { - if (opts._debug) { + if (opts._debug !== undefined) { opts._debug(`BLS12PAIRING (0x10) failed: ${e.message}`) } return EvmErrorResult(e, opts.gasLimit) @@ -131,8 +132,8 @@ export async function precompile10(opts: PrecompileInput): Promise { returnValue = zeroBuffer } - if (opts._debug) { - opts._debug(`BLS12PAIRING (0x10) return value=${returnValue.toString('hex')}`) + if (opts._debug !== undefined) { + opts._debug(`BLS12PAIRING (0x10) return value=${bytesToHex(returnValue)}`) } return { diff --git a/packages/evm/src/precompiles/11-bls12-map-fp-to-g1.ts b/packages/evm/src/precompiles/11-bls12-map-fp-to-g1.ts index f7ca9ec4df..721e8b89ad 100644 --- a/packages/evm/src/precompiles/11-bls12-map-fp-to-g1.ts +++ b/packages/evm/src/precompiles/11-bls12-map-fp-to-g1.ts @@ -1,4 +1,5 @@ import { short } from '@ethereumjs/util' +import { bytesToHex, equalsBytes } from 'ethereum-cryptography/utils' import { EvmErrorResult, OOGResult } from '../evm' import { ERROR, EvmError } from '../exceptions' @@ -15,7 +16,7 @@ export async function precompile11(opts: PrecompileInput): Promise { // note: the gas used is constant; even if the input is incorrect. const gasUsed = opts._common.paramByEIP('gasPrices', 'Bls12381MapG1Gas', 2537) ?? BigInt(0) - if (opts._debug) { + if (opts._debug !== undefined) { opts._debug( `Run BLS12MAPFPTOG1 (0x11) precompile data=${short(opts.data)} length=${ opts.data.length @@ -24,23 +25,23 @@ export async function precompile11(opts: PrecompileInput): Promise { } if (opts.gasLimit < gasUsed) { - if (opts._debug) { + if (opts._debug !== undefined) { opts._debug(`BLS12MAPFPTOG1 (0x11) failed: OOG`) } return OOGResult(opts.gasLimit) } if (inputData.length !== 64) { - if (opts._debug) { + if (opts._debug !== undefined) { opts._debug(`BLS12MAPFPTOG1 (0x11) failed: Invalid input length length=${inputData.length}`) } return EvmErrorResult(new EvmError(ERROR.BLS_12_381_INVALID_INPUT_LENGTH), opts.gasLimit) } // check if some parts of input are zero bytes. - const zeroBytes16 = Buffer.alloc(16, 0) - if (!opts.data.slice(0, 16).equals(zeroBytes16)) { - if (opts._debug) { + const zeroBytes16 = new Uint8Array(16) + if (!equalsBytes(opts.data.subarray(0, 16), zeroBytes16)) { + if (opts._debug !== undefined) { opts._debug(`BLS12MAPFPTOG1 (0x11) failed: Point not on curve`) } return EvmErrorResult(new EvmError(ERROR.BLS_12_381_POINT_NOT_ON_CURVE), opts.gasLimit) @@ -50,9 +51,9 @@ export async function precompile11(opts: PrecompileInput): Promise { let Fp1Point try { - Fp1Point = BLS12_381_ToFpPoint(opts.data.slice(0, 64), mcl) + Fp1Point = BLS12_381_ToFpPoint(opts.data.subarray(0, 64), mcl) } catch (e: any) { - if (opts._debug) { + if (opts._debug !== undefined) { opts._debug(`BLS12MAPFPTOG1 (0x11) failed: ${e.message}`) } return EvmErrorResult(e, opts.gasLimit) @@ -63,8 +64,8 @@ export async function precompile11(opts: PrecompileInput): Promise { const returnValue = BLS12_381_FromG1Point(result) - if (opts._debug) { - opts._debug(`BLS12MAPFPTOG1 (0x11) return value=${returnValue.toString('hex')}`) + if (opts._debug !== undefined) { + opts._debug(`BLS12MAPFPTOG1 (0x11) return value=${bytesToHex(returnValue)}`) } return { diff --git a/packages/evm/src/precompiles/12-bls12-map-fp2-to-g2.ts b/packages/evm/src/precompiles/12-bls12-map-fp2-to-g2.ts index 006b724910..7c573a97d5 100644 --- a/packages/evm/src/precompiles/12-bls12-map-fp2-to-g2.ts +++ b/packages/evm/src/precompiles/12-bls12-map-fp2-to-g2.ts @@ -1,4 +1,5 @@ import { short } from '@ethereumjs/util' +import { bytesToHex, equalsBytes } from 'ethereum-cryptography/utils' import { EvmErrorResult, OOGResult } from '../evm' import { ERROR, EvmError } from '../exceptions' @@ -15,7 +16,7 @@ export async function precompile12(opts: PrecompileInput): Promise { // note: the gas used is constant; even if the input is incorrect. const gasUsed = opts._common.paramByEIP('gasPrices', 'Bls12381MapG2Gas', 2537) ?? BigInt(0) - if (opts._debug) { + if (opts._debug !== undefined) { opts._debug( `Run BLS12MAPFP2TOG2 (0x12) precompile data=${short(opts.data)} length=${ opts.data.length @@ -24,30 +25,30 @@ export async function precompile12(opts: PrecompileInput): Promise { } if (opts.gasLimit < gasUsed) { - if (opts._debug) { + if (opts._debug !== undefined) { opts._debug(`BLS12MAPFP2TOG2 (0x12) failed: OOG`) } return OOGResult(opts.gasLimit) } if (inputData.length !== 128) { - if (opts._debug) { + if (opts._debug !== undefined) { opts._debug(`BLS12MAPFP2TOG2 (0x12) failed: Invalid input length length=${inputData.length}`) } return EvmErrorResult(new EvmError(ERROR.BLS_12_381_INVALID_INPUT_LENGTH), opts.gasLimit) } // check if some parts of input are zero bytes. - const zeroBytes16 = Buffer.alloc(16, 0) + const zeroBytes16 = new Uint8Array(16) const zeroByteCheck = [ [0, 16], [64, 80], ] for (const index in zeroByteCheck) { - const slicedBuffer = opts.data.slice(zeroByteCheck[index][0], zeroByteCheck[index][1]) - if (!slicedBuffer.equals(zeroBytes16)) { - if (opts._debug) { + const slicedBuffer = opts.data.subarray(zeroByteCheck[index][0], zeroByteCheck[index][1]) + if (!(equalsBytes(slicedBuffer, zeroBytes16) === true)) { + if (opts._debug !== undefined) { opts._debug(`BLS12MAPFP2TOG2 (0x12) failed: Point not on curve`) } return EvmErrorResult(new EvmError(ERROR.BLS_12_381_POINT_NOT_ON_CURVE), opts.gasLimit) @@ -58,9 +59,9 @@ export async function precompile12(opts: PrecompileInput): Promise { let Fp2Point try { - Fp2Point = BLS12_381_ToFp2Point(opts.data.slice(0, 64), opts.data.slice(64, 128), mcl) + Fp2Point = BLS12_381_ToFp2Point(opts.data.subarray(0, 64), opts.data.subarray(64, 128), mcl) } catch (e: any) { - if (opts._debug) { + if (opts._debug !== undefined) { opts._debug(`BLS12MAPFP2TOG2 (0x12) failed: ${e.message}`) } return EvmErrorResult(e, opts.gasLimit) @@ -70,8 +71,8 @@ export async function precompile12(opts: PrecompileInput): Promise { const returnValue = BLS12_381_FromG2Point(result) - if (opts._debug) { - opts._debug(`BLS12MAPFP2TOG2 (0x12) return value=${returnValue.toString('hex')}`) + if (opts._debug !== undefined) { + opts._debug(`BLS12MAPFP2TOG2 (0x12) return value=${bytesToHex(returnValue)}`) } return { diff --git a/packages/evm/src/precompiles/14-kzg-point-evaluation.ts b/packages/evm/src/precompiles/14-kzg-point-evaluation.ts index a41fdfc8d0..5db899a67b 100644 --- a/packages/evm/src/precompiles/14-kzg-point-evaluation.ts +++ b/packages/evm/src/precompiles/14-kzg-point-evaluation.ts @@ -1,5 +1,12 @@ import { computeVersionedHash, kzg } from '@ethereumjs/tx' -import { bigIntToBuffer, bufferToBigInt, bufferToHex, setLengthLeft, short } from '@ethereumjs/util' +import { + bigIntToBytes, + bytesToBigInt, + bytesToHex, + concatBytesNoTypeCheck, + setLengthLeft, + short, +} from '@ethereumjs/util' import { EvmErrorResult } from '../evm' import { ERROR, EvmError } from '../exceptions' @@ -13,7 +20,7 @@ export const BLS_MODULUS = BigInt( export async function precompile14(opts: PrecompileInput): Promise { const gasUsed = opts._common.param('gasPrices', 'kzgPointEvaluationGasPrecompilePrice') - if (opts._debug) { + if (opts._debug !== undefined) { opts._debug( `Run KZG_POINT_EVALUATION (0x14) precompile data=${short(opts.data)} length=${ opts.data.length @@ -23,52 +30,50 @@ export async function precompile14(opts: PrecompileInput): Promise { const version = Number(opts._common.paramByEIP('sharding', 'blobCommitmentVersionKzg', 4844)) const fieldElementsPerBlob = opts._common.paramByEIP('sharding', 'fieldElementsPerBlob', 4844)! - const versionedHash = opts.data.slice(0, 32) - const z = opts.data.slice(32, 64) - const y = opts.data.slice(64, 96) - const commitment = opts.data.slice(96, 144) - const kzgProof = opts.data.slice(144, 192) + const versionedHash = opts.data.subarray(0, 32) + const z = opts.data.subarray(32, 64) + const y = opts.data.subarray(64, 96) + const commitment = opts.data.subarray(96, 144) + const kzgProof = opts.data.subarray(144, 192) - if (bufferToBigInt(z) >= BLS_MODULUS || bufferToBigInt(y) >= BLS_MODULUS) { - if (opts._debug) { + if (bytesToBigInt(z) >= BLS_MODULUS || bytesToBigInt(y) >= BLS_MODULUS) { + if (opts._debug !== undefined) { opts._debug(`KZG_POINT_EVALUATION (0x14) failed: POINT_GREATER_THAN_BLS_MODULUS`) } + return EvmErrorResult(new EvmError(ERROR.POINT_GREATER_THAN_BLS_MODULUS), opts.gasLimit) } - if ( - bufferToHex(Buffer.from(computeVersionedHash(commitment, version))) !== - bufferToHex(versionedHash) - ) { - if (opts._debug) { + if (bytesToHex(computeVersionedHash(commitment, version)) !== bytesToHex(versionedHash)) { + if (opts._debug !== undefined) { opts._debug(`KZG_POINT_EVALUATION (0x14) failed: INVALID_COMMITMENT`) } return EvmErrorResult(new EvmError(ERROR.INVALID_COMMITMENT), opts.gasLimit) } - if (opts._debug) { + if (opts._debug !== undefined) { opts._debug( - `KZG_POINT_EVALUATION (0x14): proof verification with commitment=${commitment.toString( - 'hex' - )} z=${z.toString('hex')} y=${y.toString('hex')} kzgProof=${kzgProof.toString('hex')}` + `KZG_POINT_EVALUATION (0x14): proof verification with commitment=${bytesToHex( + commitment + )} z=${bytesToHex(z)} y=${bytesToHex(y)} kzgProof=${bytesToHex(kzgProof)}` ) } kzg.verifyKzgProof(commitment, z, y, kzgProof) // Return value - FIELD_ELEMENTS_PER_BLOB and BLS_MODULUS as padded 32 byte big endian values - const fieldElements = setLengthLeft(bigIntToBuffer(fieldElementsPerBlob), 32) - const modulus = setLengthLeft(bigIntToBuffer(BLS_MODULUS), 32) + const fieldElementsBuffer = setLengthLeft(bigIntToBytes(fieldElementsPerBlob), 32) + const modulusBuffer = setLengthLeft(bigIntToBytes(BLS_MODULUS), 32) - if (opts._debug) { + if (opts._debug !== undefined) { opts._debug( - `KZG_POINT_EVALUATION (0x14) return fieldElements=${fieldElements.toString( - 'hex' - )} modulus=${modulus.toString('hex')}` + `KZG_POINT_EVALUATION (0x14) return fieldElements=${bytesToHex( + fieldElementsBuffer + )} modulus=${bytesToHex(modulusBuffer)}` ) } return { executionGasUsed: gasUsed, - returnValue: Buffer.concat([fieldElements, modulus]), + returnValue: concatBytesNoTypeCheck(fieldElementsBuffer, modulusBuffer), } } diff --git a/packages/evm/src/precompiles/index.ts b/packages/evm/src/precompiles/index.ts index 843ed394f6..866a9f7f34 100644 --- a/packages/evm/src/precompiles/index.ts +++ b/packages/evm/src/precompiles/index.ts @@ -1,5 +1,6 @@ import { Hardfork } from '@ethereumjs/common' import { Address } from '@ethereumjs/util' +import { bytesToHex, hexToBytes } from 'ethereum-cryptography/utils' import { precompile01 } from './01-ecrecover' import { precompile02 } from './02-sha256' @@ -154,7 +155,7 @@ const precompileAvailability: PrecompileAvailability = { } function getPrecompile(address: Address, common: Common): PrecompileFunc { - const addr = address.buf.toString('hex') + const addr = bytesToHex(address.bytes) if (precompiles[addr] !== undefined) { const availability = precompileAvailability[addr] if ( @@ -188,7 +189,7 @@ function getActivePrecompiles( if (customPrecompiles) { for (const precompile of customPrecompiles) { precompileMap.set( - precompile.address.buf.toString('hex'), + bytesToHex(precompile.address.bytes), 'function' in precompile ? precompile.function : undefined ) } @@ -197,7 +198,8 @@ function getActivePrecompiles( if (precompileMap.has(addressString)) { continue } - const address = new Address(Buffer.from(addressString, 'hex')) + + const address = new Address(hexToBytes(addressString)) const precompileFunc = getPrecompile(address, common) if (precompileFunc !== undefined) { precompileMap.set(addressString, precompileFunc) diff --git a/packages/evm/src/precompiles/types.ts b/packages/evm/src/precompiles/types.ts index 8bd66ec91e..d9c1c5f2db 100644 --- a/packages/evm/src/precompiles/types.ts +++ b/packages/evm/src/precompiles/types.ts @@ -8,7 +8,7 @@ export interface PrecompileFunc { } export interface PrecompileInput { - data: Buffer + data: Uint8Array gasLimit: bigint _common: Common _EVM: EVMInterface diff --git a/packages/evm/src/precompiles/util/bls12_381.ts b/packages/evm/src/precompiles/util/bls12_381.ts index 522ae0536c..0fe8b79814 100644 --- a/packages/evm/src/precompiles/util/bls12_381.ts +++ b/packages/evm/src/precompiles/util/bls12_381.ts @@ -1,4 +1,5 @@ -import { bufferToBigInt, padToEven } from '@ethereumjs/util' +import { bytesToBigInt, concatBytesNoTypeCheck, padToEven } from '@ethereumjs/util' +import { bytesToHex, equalsBytes, hexToBytes } from 'ethereum-cryptography/utils' import { ERROR, EvmError } from '../../exceptions' @@ -141,9 +142,9 @@ export const gasDiscountPairs = [ // convert an input Buffer to a mcl G1 point // this does /NOT/ do any input checks. the input Buffer needs to be of length 128 // it does raise an error if the point is not on the curve. -function BLS12_381_ToG1Point(input: Buffer, mcl: any): any { - const p_x = input.slice(16, 64).toString('hex') - const p_y = input.slice(80, 128).toString('hex') +function BLS12_381_ToG1Point(input: Uint8Array, mcl: any): any { + const p_x = bytesToHex(input.subarray(16, 64)) + const p_y = bytesToHex(input.subarray(80, 128)) const ZeroString48Bytes = '0'.repeat(96) if (p_x === p_y && p_x === ZeroString48Bytes) { @@ -178,13 +179,13 @@ function BLS12_381_ToG1Point(input: Buffer, mcl: any): any { // input: a mcl G1 point // output: a 128-byte Buffer -function BLS12_381_FromG1Point(input: any): Buffer { +function BLS12_381_FromG1Point(input: any): Uint8Array { // TODO: figure out if there is a better way to decode these values. const decodeStr = input.getStr(16) //return a string of pattern "1 " const decoded = decodeStr.match(/"?[0-9a-f]+"?/g) // match above pattern. if (decodeStr === '0') { - return Buffer.alloc(128, 0) + return new Uint8Array(128) } // note: decoded[0] === 1 @@ -193,27 +194,27 @@ function BLS12_381_FromG1Point(input: any): Buffer { // convert to buffers. - const xBuffer = Buffer.concat([Buffer.alloc(64 - xval.length / 2, 0), Buffer.from(xval, 'hex')]) - const yBuffer = Buffer.concat([Buffer.alloc(64 - yval.length / 2, 0), Buffer.from(yval, 'hex')]) + const xBuffer = concatBytesNoTypeCheck(new Uint8Array(64 - xval.length / 2), hexToBytes(xval)) + const yBuffer = concatBytesNoTypeCheck(new Uint8Array(64 - yval.length / 2), hexToBytes(yval)) - return Buffer.concat([xBuffer, yBuffer]) + return concatBytesNoTypeCheck(xBuffer, yBuffer) } // convert an input Buffer to a mcl G2 point // this does /NOT/ do any input checks. the input Buffer needs to be of length 256 -function BLS12_381_ToG2Point(input: Buffer, mcl: any): any { - const p_x_1 = input.slice(0, 64) - const p_x_2 = input.slice(64, 128) - const p_y_1 = input.slice(128, 192) - const p_y_2 = input.slice(192, 256) +function BLS12_381_ToG2Point(input: Uint8Array, mcl: any): any { + const p_x_1 = input.subarray(0, 64) + const p_x_2 = input.subarray(64, 128) + const p_y_1 = input.subarray(128, 192) + const p_y_2 = input.subarray(192, 256) - const ZeroBytes64 = Buffer.alloc(64, 0) + const ZeroBytes64 = new Uint8Array(64) // check if we have to do with a zero point if ( - p_x_1.equals(p_x_2) && - p_x_1.equals(p_y_1) && - p_x_1.equals(p_y_2) && - p_x_1.equals(ZeroBytes64) + equalsBytes(p_x_1, p_x_2) && + equalsBytes(p_x_1, p_y_1) && + equalsBytes(p_x_1, p_y_2) && + equalsBytes(p_x_1, ZeroBytes64) ) { return new mcl.G2() } @@ -251,11 +252,11 @@ function BLS12_381_ToG2Point(input: Buffer, mcl: any): any { // input: a mcl G2 point // output: a 256-byte Buffer -function BLS12_381_FromG2Point(input: any): Buffer { +function BLS12_381_FromG2Point(input: any): Uint8Array { // TODO: figure out if there is a better way to decode these values. const decodeStr = input.getStr(16) //return a string of pattern "1 " if (decodeStr === '0') { - return Buffer.alloc(256, 0) + return new Uint8Array(256) } const decoded = decodeStr.match(/"?[0-9a-f]+"?/g) // match above pattern. @@ -267,19 +268,19 @@ function BLS12_381_FromG2Point(input: any): Buffer { // convert to buffers. - const xBuffer1 = Buffer.concat([Buffer.alloc(64 - x_1.length / 2, 0), Buffer.from(x_1, 'hex')]) - const xBuffer2 = Buffer.concat([Buffer.alloc(64 - x_2.length / 2, 0), Buffer.from(x_2, 'hex')]) - const yBuffer1 = Buffer.concat([Buffer.alloc(64 - y_1.length / 2, 0), Buffer.from(y_1, 'hex')]) - const yBuffer2 = Buffer.concat([Buffer.alloc(64 - y_2.length / 2, 0), Buffer.from(y_2, 'hex')]) + const xBuffer1 = concatBytesNoTypeCheck(new Uint8Array(64 - x_1.length / 2), hexToBytes(x_1)) + const xBuffer2 = concatBytesNoTypeCheck(new Uint8Array(64 - x_2.length / 2), hexToBytes(x_2)) + const yBuffer1 = concatBytesNoTypeCheck(new Uint8Array(64 - y_1.length / 2), hexToBytes(y_1)) + const yBuffer2 = concatBytesNoTypeCheck(new Uint8Array(64 - y_2.length / 2), hexToBytes(y_2)) - return Buffer.concat([xBuffer1, xBuffer2, yBuffer1, yBuffer2]) + return concatBytesNoTypeCheck(xBuffer1, xBuffer2, yBuffer1, yBuffer2) } // input: a 32-byte hex scalar Buffer // output: a mcl Fr point -function BLS12_381_ToFrPoint(input: Buffer, mcl: any): any { - const mclHex = mcl.fromHexStr(input.toString('hex')) +function BLS12_381_ToFrPoint(input: Uint8Array, mcl: any): any { + const mclHex = mcl.fromHexStr(bytesToHex(input)) const Fr = new mcl.Fr() Fr.setBigEndianMod(mclHex) return Fr @@ -288,15 +289,15 @@ function BLS12_381_ToFrPoint(input: Buffer, mcl: any): any { // input: a 64-byte buffer // output: a mcl Fp point -function BLS12_381_ToFpPoint(fpCoordinate: Buffer, mcl: any): any { +function BLS12_381_ToFpPoint(fpCoordinate: Uint8Array, mcl: any): any { // check if point is in field - if (bufferToBigInt(fpCoordinate) >= fieldModulus) { + if (bytesToBigInt(fpCoordinate) >= fieldModulus) { throw new EvmError(ERROR.BLS_12_381_FP_NOT_IN_FIELD) } const fp = new mcl.Fp() - fp.setBigEndianMod(mcl.fromHexStr(fpCoordinate.toString('hex'))) + fp.setBigEndianMod(mcl.fromHexStr(bytesToHex(fpCoordinate))) return fp } @@ -304,12 +305,12 @@ function BLS12_381_ToFpPoint(fpCoordinate: Buffer, mcl: any): any { // input: two 64-byte buffers // output: a mcl Fp2 point -function BLS12_381_ToFp2Point(fpXCoordinate: Buffer, fpYCoordinate: Buffer, mcl: any): any { +function BLS12_381_ToFp2Point(fpXCoordinate: Uint8Array, fpYCoordinate: Uint8Array, mcl: any): any { // check if the coordinates are in the field - if (bufferToBigInt(fpXCoordinate) >= fieldModulus) { + if (bytesToBigInt(fpXCoordinate) >= fieldModulus) { throw new EvmError(ERROR.BLS_12_381_FP_NOT_IN_FIELD) } - if (bufferToBigInt(fpYCoordinate) >= fieldModulus) { + if (bytesToBigInt(fpYCoordinate) >= fieldModulus) { throw new EvmError(ERROR.BLS_12_381_FP_NOT_IN_FIELD) } @@ -317,8 +318,8 @@ function BLS12_381_ToFp2Point(fpXCoordinate: Buffer, fpYCoordinate: Buffer, mcl: const fp_y = new mcl.Fp() const fp2 = new mcl.Fp2() - fp_x.setStr(fpXCoordinate.slice(16).toString('hex'), 16) - fp_y.setStr(fpYCoordinate.slice(16).toString('hex'), 16) + fp_x.setStr(bytesToHex(fpXCoordinate.subarray(16)), 16) + fp_y.setStr(bytesToHex(fpYCoordinate.subarray(16)), 16) fp2.set_a(fp_x) fp2.set_b(fp_y) diff --git a/packages/evm/src/transientStorage.ts b/packages/evm/src/transientStorage.ts index 8c641cad92..4331e8dc58 100644 --- a/packages/evm/src/transientStorage.ts +++ b/packages/evm/src/transientStorage.ts @@ -1,12 +1,14 @@ +import { bytesToHex } from '@ethereumjs/util' + import type { TransientStorageInterface } from './types' import type { Address } from '@ethereumjs/util' -type TransientStorageCurrent = Map> +type TransientStorageCurrent = Map> interface TransientStorageModification { addr: string key: string - prevValue: Buffer + prevValue: Uint8Array } type TransientStorageJournal = TransientStorageModification[] @@ -30,14 +32,14 @@ export class TransientStorage implements TransientStorageInterface { * @param addr the address for which transient storage is accessed * @param key the key of the address to get */ - public get(addr: Address, key: Buffer): Buffer { + public get(addr: Address, key: Uint8Array): Uint8Array { const map = this._storage.get(addr.toString()) if (!map) { - return Buffer.alloc(32) + return new Uint8Array(32) } - const value = map.get(key.toString('hex')) + const value = map.get(bytesToHex(key)) if (!value) { - return Buffer.alloc(32) + return new Uint8Array(32) } return value } @@ -48,7 +50,7 @@ export class TransientStorage implements TransientStorageInterface { * @param key the slot to set for the address * @param value the new value of the transient storage slot to set */ - public put(addr: Address, key: Buffer, value: Buffer) { + public put(addr: Address, key: Uint8Array, value: Uint8Array) { if (key.length !== 32) { throw new Error('Transient storage key must be 32 bytes long') } @@ -63,8 +65,8 @@ export class TransientStorage implements TransientStorageInterface { } const map = this._storage.get(addrString)! - const keyStr = key.toString('hex') - const prevValue = map.get(keyStr) ?? Buffer.alloc(32) + const keyStr = bytesToHex(key) + const prevValue = map.get(keyStr) ?? new Uint8Array(32) this._changeJournal.push({ addr: addrString, @@ -113,7 +115,7 @@ export class TransientStorage implements TransientStorageInterface { for (const [address, map] of this._storage.entries()) { result[address] = {} for (const [key, value] of map.entries()) { - result[address][key] = value.toString('hex') + result[address][key] = bytesToHex(value) } } return result diff --git a/packages/evm/src/types.ts b/packages/evm/src/types.ts index df8310955e..339e4fc7fa 100644 --- a/packages/evm/src/types.ts +++ b/packages/evm/src/types.ts @@ -28,8 +28,8 @@ export interface EVMInterface { */ export interface EEIInterface extends EVMStateAccess { getBlockHash(num: bigint): Promise - storageStore(address: Address, key: Buffer, value: Buffer): Promise - storageLoad(address: Address, key: Buffer, original: boolean): Promise + storageStore(address: Address, key: Uint8Array, value: Uint8Array): Promise + storageLoad(address: Address, key: Uint8Array, original: boolean): Promise copy(): EEIInterface } @@ -41,10 +41,10 @@ export interface EEIInterface extends EVMStateAccess { * An implementation of this can be found in the `@ethereumjs/vm` package. */ export interface EVMStateAccess extends StateAccess { - addWarmedAddress(address: Buffer): void - isWarmedAddress(address: Buffer): boolean - addWarmedStorage(address: Buffer, slot: Buffer): void - isWarmedStorage(address: Buffer, slot: Buffer): boolean + addWarmedAddress(address: Uint8Array): void + isWarmedAddress(address: Uint8Array): boolean + addWarmedStorage(address: Uint8Array, slot: Uint8Array): void + isWarmedStorage(address: Uint8Array, slot: Uint8Array): boolean clearWarmedAccounts(): void generateAccessList?(addressesRemoved: Address[], addressesOnlyStorage: Address[]): AccessList clearOriginalStorageCache(): void @@ -101,11 +101,11 @@ export interface EVMRunCallOpts { /** * The data for the call. */ - data?: Buffer + data?: Uint8Array /** * This is for CALLCODE where the code to load is different than the code from the `opts.to` address. */ - code?: Buffer + code?: Uint8Array /** * The call depth. Defaults to `0` */ @@ -121,7 +121,7 @@ export interface EVMRunCallOpts { /** * An optional salt to pass to CREATE2. */ - salt?: Buffer + salt?: Uint8Array /** * Addresses to selfdestruct. Defaults to none. */ @@ -146,7 +146,7 @@ export interface EVMRunCallOpts { /** * Versioned hashes for each blob in a blob transaction */ - versionedHashes?: Buffer[] + versionedHashes?: Uint8Array[] } /** @@ -176,11 +176,11 @@ export interface EVMRunCodeOpts { /** * The EVM code to run. */ - code?: Buffer + code?: Uint8Array /** * The input data. */ - data?: Buffer + data?: Uint8Array /** * The gas limit for the call. */ @@ -212,13 +212,13 @@ export interface EVMRunCodeOpts { /** * Versioned hashes for each blob in a blob transaction */ - versionedHashes?: Buffer[] + versionedHashes?: Uint8Array[] } interface NewContractEvent { address: Address // The deployment code - code: Buffer + code: Uint8Array } export type EVMEvents = { @@ -231,7 +231,7 @@ export type EVMEvents = { /** * Log that the contract emits. */ -export type Log = [address: Buffer, topics: Buffer[], data: Buffer] +export type Log = [address: Uint8Array, topics: Uint8Array[], data: Uint8Array] declare type AccessListItem = { address: PrefixedHexString @@ -264,19 +264,19 @@ interface StateAccess { accountIsEmpty(address: Address): Promise deleteAccount(address: Address): Promise modifyAccountFields(address: Address, accountFields: AccountFields): Promise - putContractCode(address: Address, value: Buffer): Promise - getContractCode(address: Address): Promise - getContractStorage(address: Address, key: Buffer): Promise - putContractStorage(address: Address, key: Buffer, value: Buffer): Promise + putContractCode(address: Address, value: Uint8Array): Promise + getContractCode(address: Address): Promise + getContractStorage(address: Address, key: Uint8Array): Promise + putContractStorage(address: Address, key: Uint8Array, value: Uint8Array): Promise clearContractStorage(address: Address): Promise checkpoint(): Promise commit(): Promise revert(): Promise - getStateRoot(): Promise - setStateRoot(stateRoot: Buffer): Promise - getProof?(address: Address, storageSlots: Buffer[]): Promise + getStateRoot(): Promise + setStateRoot(stateRoot: Uint8Array): Promise + getProof?(address: Address, storageSlots: Uint8Array[]): Promise verifyProof?(proof: Proof): Promise - hasStateRoot(root: Buffer): Promise + hasStateRoot(root: Uint8Array): Promise } export type Block = { @@ -286,15 +286,15 @@ export type Block = { coinbase: Address timestamp: bigint difficulty: bigint - prevRandao: Buffer + prevRandao: Uint8Array gasLimit: bigint baseFeePerGas?: bigint } } export interface TransientStorageInterface { - get(addr: Address, key: Buffer): Buffer - put(addr: Address, key: Buffer, value: Buffer): void + get(addr: Address, key: Uint8Array): Uint8Array + put(addr: Address, key: Uint8Array, value: Uint8Array): void commit(): void checkpoint(): void revert(): void diff --git a/packages/evm/test/asyncEvents.spec.ts b/packages/evm/test/asyncEvents.spec.ts index 2d0735d87b..d6033e0a5b 100644 --- a/packages/evm/test/asyncEvents.spec.ts +++ b/packages/evm/test/asyncEvents.spec.ts @@ -1,5 +1,6 @@ import { Chain, Common, Hardfork } from '@ethereumjs/common' import { Address } from '@ethereumjs/util' +import { hexToBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' import { EVM } from '../src' @@ -8,7 +9,7 @@ import { getEEI } from './utils' tape('async events', async (t) => { t.plan(2) - const caller = new Address(Buffer.from('00000000000000000000000000000000000000ee', 'hex')) + const caller = new Address(hexToBytes('00000000000000000000000000000000000000ee')) const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Constantinople }) const eei = await getEEI() const evm = await EVM.create({ common, eei }) @@ -22,7 +23,7 @@ tape('async events', async (t) => { const runCallArgs = { caller, // call address gasLimit: BigInt(0xffffffffff), - data: Buffer.from('600000', 'hex'), + data: hexToBytes('600000'), } await evm.runCall(runCallArgs) }) diff --git a/packages/evm/test/customOpcodes.spec.ts b/packages/evm/test/customOpcodes.spec.ts index 2d4155ba25..6439c6dac3 100644 --- a/packages/evm/test/customOpcodes.spec.ts +++ b/packages/evm/test/customOpcodes.spec.ts @@ -1,3 +1,4 @@ +import { equalsBytes, hexToBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' import { EVM } from '../src/evm' @@ -38,7 +39,7 @@ tape('VM: custom opcodes', (t) => { } }) const res = await evm.runCode({ - code: Buffer.from('21', 'hex'), + code: hexToBytes('21'), gasLimit: BigInt(gas), }) st.ok(res.executionGasUsed === totalFee, 'successfully charged correct gas') @@ -53,7 +54,7 @@ tape('VM: custom opcodes', (t) => { }) const gas = BigInt(123456) const res = await evm.runCode({ - code: Buffer.from('20', 'hex'), + code: hexToBytes('20'), gasLimit: BigInt(gas), }) st.ok(res.executionGasUsed === gas, 'successfully deleted opcode') @@ -68,7 +69,7 @@ tape('VM: custom opcodes', (t) => { }) const gas = BigInt(123456) const res = await evm.runCode({ - code: Buffer.from('01', 'hex'), + code: hexToBytes('01'), gasLimit: BigInt(gas), }) st.ok(res.executionGasUsed === gas, 'successfully deleted opcode') @@ -85,10 +86,10 @@ tape('VM: custom opcodes', (t) => { // PUSH 1F // RETURNDATA offset // RETURN // Returns 0x05 const result = await evmDefault.runCode!({ - code: Buffer.from('60046001016000526001601FF3', 'hex'), + code: hexToBytes('60046001016000526001601FF3'), gasLimit: BigInt(gas), }) - st.ok(result.returnValue.equals(Buffer.from('05', 'hex'))) + st.ok(equalsBytes(result.returnValue, hexToBytes('05'))) }) t.test('should override opcodes in the EVM', async (st) => { @@ -99,7 +100,7 @@ tape('VM: custom opcodes', (t) => { }) const gas = 123456 const res = await evm.runCode({ - code: Buffer.from('20', 'hex'), + code: hexToBytes('20'), gasLimit: BigInt(gas), }) st.ok(res.executionGasUsed === totalFee, 'successfully charged correct gas') diff --git a/packages/evm/test/customPrecompiles.spec.ts b/packages/evm/test/customPrecompiles.spec.ts index 5492c12fde..ba6af03d9e 100644 --- a/packages/evm/test/customPrecompiles.spec.ts +++ b/packages/evm/test/customPrecompiles.spec.ts @@ -1,4 +1,5 @@ import { Address } from '@ethereumjs/util' +import { hexToBytes, utf8ToBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' import { EVM } from '../src/evm' @@ -8,10 +9,10 @@ import { getEEI } from './utils' import type { ExecResult } from '../src/evm' import type { PrecompileInput } from '../src/precompiles' -const sender = new Address(Buffer.from('44'.repeat(20), 'hex')) -const newPrecompile = new Address(Buffer.from('ff'.repeat(20), 'hex')) -const shaAddress = new Address(Buffer.from('0000000000000000000000000000000000000002', 'hex')) -const expectedReturn = Buffer.from('1337', 'hex') +const sender = new Address(hexToBytes('44'.repeat(20))) +const newPrecompile = new Address(hexToBytes('ff'.repeat(20))) +const shaAddress = new Address(hexToBytes('0000000000000000000000000000000000000002')) +const expectedReturn = utf8ToBytes('1337') const expectedGas = BigInt(10) function customPrecompile(_input: PrecompileInput): ExecResult { @@ -35,11 +36,12 @@ tape('EVM -> custom precompiles', (t) => { const result = await EVMOverride.runCall({ to: shaAddress, gasLimit: BigInt(30000), - data: Buffer.from(''), + data: utf8ToBytes(''), caller: sender, }) - st.ok(result.execResult.returnValue.equals(expectedReturn), 'return value is correct') - st.ok(result.execResult.executionGasUsed === expectedGas, 'gas used is correct') + + st.deepEquals(result.execResult.returnValue, expectedReturn, 'return value is correct') + st.equals(result.execResult.executionGasUsed, expectedGas, 'gas used is correct') }) t.test('should delete existing precompiles', async (st) => { @@ -54,11 +56,11 @@ tape('EVM -> custom precompiles', (t) => { const result = await EVMOverride.runCall({ to: shaAddress, gasLimit: BigInt(30000), - data: Buffer.from(''), + data: hexToBytes(''), caller: sender, }) - st.ok(result.execResult.returnValue.equals(Buffer.from('')), 'return value is correct') - st.ok(result.execResult.executionGasUsed === BigInt(0), 'gas used is correct') + st.deepEquals(result.execResult.returnValue, utf8ToBytes(''), 'return value is correct') + st.equals(result.execResult.executionGasUsed, BigInt(0), 'gas used is correct') }) t.test('should add precompiles', async (st) => { @@ -74,11 +76,11 @@ tape('EVM -> custom precompiles', (t) => { const result = await EVMOverride.runCall({ to: newPrecompile, gasLimit: BigInt(30000), - data: Buffer.from(''), + data: hexToBytes(''), caller: sender, }) - st.ok(result.execResult.returnValue.equals(expectedReturn), 'return value is correct') - st.ok(result.execResult.executionGasUsed === expectedGas, 'gas used is correct') + st.deepEquals(result.execResult.returnValue, expectedReturn, 'return value is correct') + st.equals(result.execResult.executionGasUsed, expectedGas, 'gas used is correct') }) t.test('should not persist changes to precompiles', async (st) => { @@ -86,7 +88,7 @@ tape('EVM -> custom precompiles', (t) => { const shaResult = await EVMSha.runCall({ to: shaAddress, gasLimit: BigInt(30000), - data: Buffer.from(''), + data: hexToBytes(''), caller: sender, }) const EVMOverride = await EVM.create({ @@ -101,25 +103,27 @@ tape('EVM -> custom precompiles', (t) => { const result = await EVMOverride.runCall({ to: shaAddress, gasLimit: BigInt(30000), - data: Buffer.from(''), + data: hexToBytes(''), caller: sender, }) // sanity: check we have overridden - st.ok(result.execResult.returnValue.equals(expectedReturn), 'return value is correct') - st.ok(result.execResult.executionGasUsed === expectedGas, 'gas used is correct') + st.deepEquals(result.execResult.returnValue, expectedReturn, 'return value is correct') + st.equals(result.execResult.executionGasUsed, expectedGas, 'gas used is correct') EVMSha = await EVM.create({ eei: await getEEI() }) const shaResult2 = await EVMSha.runCall({ to: shaAddress, gasLimit: BigInt(30000), - data: Buffer.from(''), + data: hexToBytes(''), caller: sender, }) - st.ok( - shaResult.execResult.returnValue.equals(shaResult2.execResult.returnValue), + st.deepEquals( + shaResult.execResult.returnValue, + shaResult2.execResult.returnValue, 'restored sha precompile - returndata correct' ) - st.ok( - shaResult.execResult.executionGasUsed === shaResult2.execResult.executionGasUsed, + st.equals( + shaResult.execResult.executionGasUsed, + shaResult2.execResult.executionGasUsed, 'restored sha precompile - gas correct' ) }) diff --git a/packages/evm/test/eips/eip-3860.spec.ts b/packages/evm/test/eips/eip-3860.spec.ts index c54d76ed7e..93cc46f793 100644 --- a/packages/evm/test/eips/eip-3860.spec.ts +++ b/packages/evm/test/eips/eip-3860.spec.ts @@ -1,11 +1,12 @@ import { Chain, Common, Hardfork } from '@ethereumjs/common' -import { Address, privateToAddress } from '@ethereumjs/util' +import { Address, concatBytesNoTypeCheck, privateToAddress } from '@ethereumjs/util' +import { concatBytes, equalsBytes, hexToBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' import { EVM } from '../../src' import { getEEI } from '../utils' -const pkey = Buffer.from('20'.repeat(32), 'hex') +const pkey = hexToBytes('20'.repeat(32)) const sender = new Address(privateToAddress(pkey)) tape('EIP 3860 tests', (t) => { @@ -18,7 +19,7 @@ tape('EIP 3860 tests', (t) => { const eei = await getEEI() const evm = await EVM.create({ common, eei }) - const buffer = Buffer.allocUnsafe(1000000).fill(0x60) + const buffer = new Uint8Array(1000000).fill(0x60) // setup the call arguments const runCallArgs = { @@ -27,13 +28,12 @@ tape('EIP 3860 tests', (t) => { // Simple test, PUSH PUSH 0 RETURN // It tries to deploy a contract too large, where the code is all zeros // (since memory which is not allocated/resized to yet is always defaulted to 0) - data: Buffer.concat([ - Buffer.from( - '0x7F6000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060005260206000F3', - 'hex' + data: concatBytesNoTypeCheck( + hexToBytes( + '0x7F6000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060005260206000F3' ), - buffer, - ]), + buffer + ), } const result = await evm.runCall(runCallArgs) st.ok( @@ -62,17 +62,13 @@ tape('EIP 3860 tests', (t) => { const contractAccount = await evm.eei.getAccount(contractFactory) await evm.eei.putAccount(contractFactory, contractAccount) await evmWithout3860.eei.putAccount(contractFactory, contractAccount) - const factoryCode = Buffer.from( - '7f600a80600080396000f3000000000000000000000000000000000000000000006000526000355a8160006000f05a8203600a55806000556001600155505050', - 'hex' + const factoryCode = hexToBytes( + '7f600a80600080396000f3000000000000000000000000000000000000000000006000526000355a8160006000f05a8203600a55806000556001600155505050' ) await evm.eei.putContractCode(contractFactory, factoryCode) await evmWithout3860.eei.putContractCode(contractFactory, factoryCode) - const data = Buffer.from( - '000000000000000000000000000000000000000000000000000000000000c000', - 'hex' - ) + const data = hexToBytes('000000000000000000000000000000000000000000000000000000000000c000') const runCallArgs = { from: caller, to: contractFactory, @@ -108,17 +104,13 @@ tape('EIP 3860 tests', (t) => { const contractAccount = await evm.eei.getAccount(contractFactory) await evm.eei.putAccount(contractFactory, contractAccount) await evmWithout3860.eei.putAccount(contractFactory, contractAccount) - const factoryCode = Buffer.from( - '7f600a80600080396000f3000000000000000000000000000000000000000000006000526000355a60008260006000f55a8203600a55806000556001600155505050', - 'hex' + const factoryCode = hexToBytes( + '7f600a80600080396000f3000000000000000000000000000000000000000000006000526000355a60008260006000f55a8203600a55806000556001600155505050' ) await evm.eei.putContractCode(contractFactory, factoryCode) await evmWithout3860.eei.putContractCode(contractFactory, factoryCode) - const data = Buffer.from( - '000000000000000000000000000000000000000000000000000000000000c000', - 'hex' - ) + const data = hexToBytes('000000000000000000000000000000000000000000000000000000000000c000') const runCallArgs = { from: caller, to: contractFactory, @@ -143,7 +135,7 @@ tape('EIP 3860 tests', (t) => { const eei = await getEEI() const evm = await EVM.create({ common, eei, allowUnlimitedInitCodeSize: true }) - const buffer = Buffer.allocUnsafe(1000000).fill(0x60) + const bytes = new Uint8Array(1000000).fill(0x60) // setup the call arguments const runCallArgs = { @@ -152,10 +144,10 @@ tape('EIP 3860 tests', (t) => { // Simple test, PUSH PUSH 0 RETURN // It tries to deploy a contract too large, where the code is all zeros // (since memory which is not allocated/resized to yet is always defaulted to 0) - data: Buffer.concat([ - Buffer.from('00'.repeat(Number(common.param('vm', 'maxInitCodeSize')) + 1), 'hex'), - buffer, - ]), + data: concatBytes( + hexToBytes('00'.repeat(Number(common.param('vm', 'maxInitCodeSize')) + 1)), + bytes + ), } const result = await evm.runCall(runCallArgs) st.ok( @@ -193,7 +185,7 @@ tape('EIP 3860 tests', (t) => { // (the initcode of this contract is just zeros, so STOP opcode // It stores the topmost stack item of this CREATE(2) at slot 0 // This is either the contract address if it was succesful, or 0 in case of error - const factoryCode = Buffer.from('600060003560006000' + code + '600055', 'hex') + const factoryCode = hexToBytes('600060003560006000' + code + '600055') await evm.eei.putContractCode(contractFactory, factoryCode) await evmDisabled.eei.putContractCode(contractFactory, factoryCode) @@ -202,22 +194,22 @@ tape('EIP 3860 tests', (t) => { from: caller, to: contractFactory, gasLimit: BigInt(0xfffffffff), - data: Buffer.from('00'.repeat(30) + 'C001', 'hex'), + data: hexToBytes('00'.repeat(30) + 'C001'), } const res = await evm.runCall(runCallArgs) await evmDisabled.runCall(runCallArgs) - const key0 = Buffer.from('00'.repeat(32), 'hex') + const key0 = hexToBytes('00'.repeat(32)) const storageActive = await evm.eei.getContractStorage(contractFactory, key0) const storageInactive = await evmDisabled.eei.getContractStorage(contractFactory, key0) st.ok( - !storageActive.equals(Buffer.from('')), + !equalsBytes(storageActive, new Uint8Array()), 'created contract with MAX_INITCODE_SIZE + 1 length, allowUnlimitedInitCodeSize=true' ) st.ok( - storageInactive.equals(Buffer.from('')), + equalsBytes(storageInactive, new Uint8Array()), 'did not create contract with MAX_INITCODE_SIZE + 1 length, allowUnlimitedInitCodeSize=false' ) @@ -227,7 +219,7 @@ tape('EIP 3860 tests', (t) => { from: caller, to: contractFactory, gasLimit: BigInt(0xfffffffff), - data: Buffer.from('00'.repeat(30) + 'C000', 'hex'), + data: hexToBytes('00'.repeat(30) + 'C000'), } // Test: diff --git a/packages/evm/test/eof.spec.ts b/packages/evm/test/eof.spec.ts index 8764f5c057..8af17a1980 100644 --- a/packages/evm/test/eof.spec.ts +++ b/packages/evm/test/eof.spec.ts @@ -1,3 +1,4 @@ +import { bytesToHex, hexToBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' import { getEOFCode } from '../src/eof' @@ -18,12 +19,12 @@ tape('getEOFCode()', (t) => { const invalidEofCode = generateInvalidEOFCode(code) t.equal( - getEOFCode(Buffer.from(validEofCode.slice(2), 'hex')).toString('hex'), + bytesToHex(getEOFCode(hexToBytes(validEofCode.slice(2)))), code, 'returned just code section of EOF container' ) t.equal( - getEOFCode(Buffer.from(invalidEofCode.slice(2), 'hex')).toString('hex'), + bytesToHex(getEOFCode(hexToBytes(invalidEofCode.slice(2)))), invalidEofCode.toLowerCase().slice(2), 'returns entire code string for non EOF code' ) diff --git a/packages/evm/test/memory.spec.ts b/packages/evm/test/memory.spec.ts index 6a0d493467..746e87d551 100644 --- a/packages/evm/test/memory.spec.ts +++ b/packages/evm/test/memory.spec.ts @@ -10,7 +10,7 @@ tape('Memory', (t) => { }) t.test('should return zeros from empty memory', (st) => { - st.ok(m.read(0, 3).equals(Buffer.from([0, 0, 0]))) + st.deepEquals(m.read(0, 3), Uint8Array.from([0, 0, 0])) st.end() }) @@ -21,18 +21,18 @@ tape('Memory', (t) => { }) t.test('should return zeros before writing', (st) => { - st.ok(m.read(0, 2).equals(Buffer.from([0, 0]))) + st.deepEquals(m.read(0, 2), Uint8Array.from([0, 0])) st.end() }) t.test('should write value', (st) => { - m.write(29, 3, Buffer.from([1, 2, 3])) - st.ok(m.read(29, 5).equals(Buffer.from([1, 2, 3, 0, 0]))) + m.write(29, 3, Uint8Array.from([1, 2, 3])) + st.deepEquals(m.read(29, 5), Uint8Array.from([1, 2, 3, 0, 0])) st.end() }) t.test('should fail when value len and size are inconsistent', (st) => { - st.throws(() => m.write(0, 5, Buffer.from([8, 8, 8])), /size/) + st.throws(() => m.write(0, 5, Uint8Array.from([8, 8, 8])), /size/) st.end() }) @@ -41,7 +41,7 @@ tape('Memory', (t) => { (st) => { const memory = new Memory() st.equal(memory._store.length, 0, 'memory should start with zero length') - memory.write(0, 1, Buffer.from([1])) + memory.write(0, 1, Uint8Array.from([1])) st.equal(memory._store.length, 8192, 'memory buffer length expanded to 8192 bytes') st.end() diff --git a/packages/evm/test/precompiles/06-ecadd.spec.ts b/packages/evm/test/precompiles/06-ecadd.spec.ts index bb1e56a8d9..113d5db14c 100644 --- a/packages/evm/test/precompiles/06-ecadd.spec.ts +++ b/packages/evm/test/precompiles/06-ecadd.spec.ts @@ -14,7 +14,7 @@ tape('Precompiles: ECADD', (t) => { const ECADD = getActivePrecompiles(common).get(addressStr)! const result = await ECADD({ - data: Buffer.alloc(0), + data: new Uint8Array(0), gasLimit: BigInt(0xffff), _common: common, _EVM: evm, diff --git a/packages/evm/test/precompiles/07-ecmul.spec.ts b/packages/evm/test/precompiles/07-ecmul.spec.ts index a48fd1f854..73f57ee4de 100644 --- a/packages/evm/test/precompiles/07-ecmul.spec.ts +++ b/packages/evm/test/precompiles/07-ecmul.spec.ts @@ -13,7 +13,7 @@ tape('Precompiles: ECMUL', (t) => { const ECMUL = getActivePrecompiles(common).get('0000000000000000000000000000000000000007')! const result = await ECMUL({ - data: Buffer.alloc(0), + data: new Uint8Array(0), gasLimit: BigInt(0xffff), _common: common, _EVM: evm, diff --git a/packages/evm/test/precompiles/08-ecpairing.spec.ts b/packages/evm/test/precompiles/08-ecpairing.spec.ts index 57550d8f84..95e96c4d0e 100644 --- a/packages/evm/test/precompiles/08-ecpairing.spec.ts +++ b/packages/evm/test/precompiles/08-ecpairing.spec.ts @@ -1,4 +1,5 @@ import { Chain, Common, Hardfork } from '@ethereumjs/common' +import { hexToBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' import { EVM } from '../../src' @@ -12,11 +13,9 @@ tape('Precompiles: ECPAIRING', (t) => { const evm = await EVM.create({ common, eei }) const addressStr = '0000000000000000000000000000000000000008' const ECPAIRING = getActivePrecompiles(common).get(addressStr)! - const result = await ECPAIRING({ - data: Buffer.from( - '00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa000000000000000000000000000000000000000000000000000000000000000130644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd45198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa', - 'hex' + data: hexToBytes( + '00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa000000000000000000000000000000000000000000000000000000000000000130644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd45198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa' ), gasLimit: BigInt(0xffffff), _common: common, diff --git a/packages/evm/test/precompiles/14-pointevaluation.spec.ts b/packages/evm/test/precompiles/14-pointevaluation.spec.ts index 2d658a469b..b6a4ca1863 100644 --- a/packages/evm/test/precompiles/14-pointevaluation.spec.ts +++ b/packages/evm/test/precompiles/14-pointevaluation.spec.ts @@ -1,7 +1,8 @@ import { Common, Hardfork } from '@ethereumjs/common' import { computeVersionedHash, initKZG } from '@ethereumjs/tx' -import { bigIntToBuffer, bufferToBigInt, unpadBuffer } from '@ethereumjs/util' +import { bigIntToBytes, bytesToBigInt, concatBytesNoTypeCheck, unpadBytes } from '@ethereumjs/util' import * as kzg from 'c-kzg' +import { hexToBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' import { EVM, getActivePrecompiles } from '../../src' @@ -24,33 +25,25 @@ tape('Precompiles: point evaluation', async (t) => { const pointEvaluation = getActivePrecompiles(common).get(addressStr)! const testCase = { - Proof: Buffer.from( - '8ad6f539bc7280de6af4c95e7cef39bb6873f18c46ee5eb67299324ee7c6e6da71be2dbd5e2cbafbae4b2d60b40a808c', - 'hex' + Proof: hexToBytes( + '8ad6f539bc7280de6af4c95e7cef39bb6873f18c46ee5eb67299324ee7c6e6da71be2dbd5e2cbafbae4b2d60b40a808c' ), - Commitment: Buffer.from( - 'abb6bcbe313530ce7779abdf633d5a3594a41fbad9a79f4a9b46b89c0cfe78f6a15948dec92c4404aedac8b5e7dd6059', - 'hex' - ), - InputPoint: Buffer.from( - '0120000000000000000000000000000000000000000000000000000000000000', - 'hex' - ), - ClaimedValue: Buffer.from( - '48cdd065593bd932707001e88674108ade9dd71d2e849e9a55fa71b70f06690f', - 'hex' + Commitment: hexToBytes( + 'abb6bcbe313530ce7779abdf633d5a3594a41fbad9a79f4a9b46b89c0cfe78f6a15948dec92c4404aedac8b5e7dd6059' ), + InputPoint: hexToBytes('0120000000000000000000000000000000000000000000000000000000000000'), + ClaimedValue: hexToBytes('48cdd065593bd932707001e88674108ade9dd71d2e849e9a55fa71b70f06690f'), } const versionedHash = computeVersionedHash(testCase.Commitment, 1) const opts: PrecompileInput = { - data: Buffer.concat([ + data: concatBytesNoTypeCheck( versionedHash, testCase.InputPoint, testCase.ClaimedValue, testCase.Commitment, - testCase.Proof, - ]), + testCase.Proof + ), gasLimit: 0xfffffffffn, _EVM: evm, _common: common, @@ -58,19 +51,19 @@ tape('Precompiles: point evaluation', async (t) => { let res = await pointEvaluation(opts) t.equal( - bufferToBigInt(unpadBuffer(res.returnValue.slice(32))), + bytesToBigInt(unpadBytes(res.returnValue.slice(32))), BLS_MODULUS, 'point evaluation precompile returned expected output' ) const optsWithBigNumbers: PrecompileInput = { - data: Buffer.concat([ + data: concatBytesNoTypeCheck( versionedHash, testCase.InputPoint, - bigIntToBuffer(BLS_MODULUS + 5n), + bigIntToBytes(BLS_MODULUS + 5n), testCase.Commitment, - testCase.Proof, - ]), + testCase.Proof + ), gasLimit: 0xfffffffffn, _EVM: evm, _common: common, @@ -84,13 +77,13 @@ tape('Precompiles: point evaluation', async (t) => { ) const optsWithInvalidCommitment: PrecompileInput = { - data: Buffer.concat([ - Buffer.concat([Uint8Array.from([0]), versionedHash.slice(1)]), + data: concatBytesNoTypeCheck( + concatBytesNoTypeCheck(Uint8Array.from([0]), versionedHash.slice(1)), testCase.InputPoint, testCase.ClaimedValue, testCase.Commitment, - testCase.Proof, - ]), + testCase.Proof + ), gasLimit: 0xfffffffffn, _EVM: evm, _common: common, diff --git a/packages/evm/test/precompiles/eip-2537-BLS.spec.ts b/packages/evm/test/precompiles/eip-2537-BLS.spec.ts index 9c4da676d5..dc8b3c5030 100644 --- a/packages/evm/test/precompiles/eip-2537-BLS.spec.ts +++ b/packages/evm/test/precompiles/eip-2537-BLS.spec.ts @@ -1,5 +1,6 @@ import { Chain, Common, Hardfork } from '@ethereumjs/common' -import { Address, bufferToHex } from '@ethereumjs/util' +import { Address, bytesToPrefixedHexString } from '@ethereumjs/util' +import { hexToBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' import { isRunningInKarma } from '../../../vm/test/util' @@ -27,13 +28,13 @@ tape('EIP-2537 BLS tests', (t) => { const evm = await EVM.create({ common, eei }) for (const address of precompiles) { - const to = new Address(Buffer.from(address, 'hex')) + const to = new Address(hexToBytes(address)) const result = await evm.runCall({ caller: Address.zero(), gasLimit: BigInt(0xffffffffff), to, value: BigInt(0), - data: Buffer.alloc(0), + data: new Uint8Array(0), }) if (result.execResult.executionGasUsed !== BigInt(0)) { @@ -59,13 +60,13 @@ tape('EIP-2537 BLS tests', (t) => { const evm = await EVM.create({ common, eei }) for (const address of precompiles) { - const to = new Address(Buffer.from(address, 'hex')) + const to = new Address(hexToBytes(address)) const result = await evm.runCall({ caller: Address.zero(), gasLimit: BigInt(0xffffffffff), to, value: BigInt(0), - data: Buffer.alloc(0), + data: new Uint8Array(0), }) if (result.execResult.executionGasUsed !== BigInt(0xffffffffff)) { @@ -106,7 +107,7 @@ tape('EIP-2537 BLS tests', (t) => { '0x00000000000000000000000000000000083ad744b34f6393bc983222b004657494232c5d9fbc978d76e2377a28a34c4528da5d91cbc0977dc953397a6d21eca20000000000000000000000000000000015aec6526e151cf5b8403353517dfb9a162087a698b71f32b266d3c5c936a83975d5567c25b3a5994042ec1379c8e526000000000000000000000000000000000e3647185d1a20efad19f975729908840dc33909a583600f7915025f906aef9c022fd34e618170b11178aaa824ae36b300000000000000000000000000000000159576d1d53f6cd12c39d651697e11798321f17cd287118d7ebeabf68281bc03109ee103ee8ef2ef93c71dd1dcbaf1e0' const result = await BLS12G2MultiExp({ - data: Buffer.from(testVector, 'hex'), + data: hexToBytes(testVector), gasLimit: BigInt(5000000), _common: common, _EVM: evm, @@ -114,7 +115,7 @@ tape('EIP-2537 BLS tests', (t) => { st.deepEqual( testVectorResult, - bufferToHex(result.returnValue), + bytesToPrefixedHexString(result.returnValue), 'return value should match testVectorResult' ) st.end() diff --git a/packages/evm/test/precompiles/hardfork.spec.ts b/packages/evm/test/precompiles/hardfork.spec.ts index 42e1a3ab3c..0ec4ce680a 100644 --- a/packages/evm/test/precompiles/hardfork.spec.ts +++ b/packages/evm/test/precompiles/hardfork.spec.ts @@ -1,5 +1,6 @@ import { Chain, Common, Hardfork } from '@ethereumjs/common' import { Address } from '@ethereumjs/util' +import { hexToBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' import { EVM } from '../../src' @@ -9,7 +10,7 @@ import { getEEI } from '../utils' tape('Precompiles: hardfork availability', (t) => { t.test('Test ECPAIRING availability', async (st) => { const ECPAIR_AddressStr = '0000000000000000000000000000000000000008' - const ECPAIR_Address = new Address(Buffer.from(ECPAIR_AddressStr, 'hex')) + const ECPAIR_Address = new Address(hexToBytes(ECPAIR_AddressStr)) // ECPAIR was introduced in Byzantium; check if available from Byzantium. const commonByzantium = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Byzantium }) diff --git a/packages/evm/test/runCall.spec.ts b/packages/evm/test/runCall.spec.ts index 320f6f6754..98d4abe245 100644 --- a/packages/evm/test/runCall.spec.ts +++ b/packages/evm/test/runCall.spec.ts @@ -1,6 +1,14 @@ import { Chain, Common, Hardfork } from '@ethereumjs/common' -import { Account, Address, MAX_UINT64, padToEven, unpadBuffer } from '@ethereumjs/util' +import { + Account, + Address, + MAX_UINT64, + concatBytesNoTypeCheck, + padToEven, + unpadBytes, +} from '@ethereumjs/util' import { keccak256 } from 'ethereum-cryptography/keccak' +import { bytesToHex, hexToBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' import { EVM } from '../src' @@ -10,11 +18,11 @@ import { getEEI } from './utils' import type { EVMRunCallOpts } from '../src/types' -// Non-protected Create2Address generator. Does not check if buffers have the right padding. -function create2address(sourceAddress: Address, codeHash: Buffer, salt: Buffer): Address { - const rlp_proc_buffer = Buffer.from('ff', 'hex') - const hashBuffer = Buffer.concat([rlp_proc_buffer, sourceAddress.buf, salt, codeHash]) - return new Address(Buffer.from(keccak256(hashBuffer)).slice(12)) +// Non-protected Create2Address generator. Does not check if Uint8Arrays have the right padding. +function create2address(sourceAddress: Address, codeHash: Uint8Array, salt: Uint8Array): Address { + const rlp_proc_bytes = hexToBytes('ff') + const hashBytes = concatBytesNoTypeCheck(rlp_proc_bytes, sourceAddress.bytes, salt, codeHash) + return new Address(keccak256(hashBytes).slice(12)) } tape('Create where FROM account nonce is 0', async (t) => { @@ -40,10 +48,8 @@ tape('Create where FROM account nonce is 0', async (t) => { tape('Constantinople: EIP-1014 CREATE2 creates the right contract address', async (t) => { // setup the accounts for this test - const caller = new Address(Buffer.from('00000000000000000000000000000000000000ee', 'hex')) // caller address - const contractAddress = new Address( - Buffer.from('00000000000000000000000000000000000000ff', 'hex') - ) // contract address + const caller = new Address(hexToBytes('00000000000000000000000000000000000000ee')) // caller address + const contractAddress = new Address(hexToBytes('00000000000000000000000000000000000000ff')) // contract address // setup the vm const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Constantinople }) const eei = await getEEI() @@ -63,9 +69,9 @@ tape('Constantinople: EIP-1014 CREATE2 creates the right contract address', asyn RETURN [0x00, 0x20] */ - await eei.putContractCode(contractAddress, Buffer.from(code, 'hex')) // setup the contract code + await eei.putContractCode(contractAddress, hexToBytes(code)) // setup the contract code await eei.putAccount(caller, new Account(BigInt(0), BigInt(0x11111111))) // give the calling account a big balance so we don't run out of funds - const codeHash = Buffer.from(keccak256(Buffer.from(''))) + const codeHash = keccak256(hexToBytes('')) for (let value = 0; value <= 1000; value += 20) { // setup the call arguments const runCallArgs = { @@ -76,14 +82,14 @@ tape('Constantinople: EIP-1014 CREATE2 creates the right contract address', asyn } const hexString = padToEven(value.toString(16)) - let valueBuffer = Buffer.from(hexString, 'hex') - // pad buffer - if (valueBuffer.length < 32) { - const diff = 32 - valueBuffer.length - valueBuffer = Buffer.concat([Buffer.alloc(diff), valueBuffer]) + let valueBytes = hexToBytes(hexString) + // pad bytes + if (valueBytes.length < 32) { + const diff = 32 - valueBytes.length + valueBytes = concatBytesNoTypeCheck(new Uint8Array(diff), valueBytes) } // calculate expected CREATE2 address - const expectedAddress = create2address(contractAddress, codeHash, valueBuffer) + const expectedAddress = create2address(contractAddress, codeHash, valueBytes) // run the actual call const res = await evm.runCall(runCallArgs) // retrieve the return value and convert it to an address (remove the first 12 bytes from the 32-byte return value) @@ -101,10 +107,8 @@ tape('Constantinople: EIP-1014 CREATE2 creates the right contract address', asyn tape('Byzantium cannot access Constantinople opcodes', async (t) => { t.plan(2) // setup the accounts for this test - const caller = new Address(Buffer.from('00000000000000000000000000000000000000ee', 'hex')) // caller address - const contractAddress = new Address( - Buffer.from('00000000000000000000000000000000000000ff', 'hex') - ) // contract address + const caller = new Address(hexToBytes('00000000000000000000000000000000000000ee')) // caller address + const contractAddress = new Address(hexToBytes('00000000000000000000000000000000000000ff')) // contract address // setup the evm const eeiByzantium = await getEEI() const eeiConstantinople = await getEEI() @@ -125,8 +129,8 @@ tape('Byzantium cannot access Constantinople opcodes', async (t) => { STOP */ - await eeiByzantium.putContractCode(contractAddress, Buffer.from(code, 'hex')) // setup the contract code - await eeiConstantinople.putContractCode(contractAddress, Buffer.from(code, 'hex')) // setup the contract code + await eeiByzantium.putContractCode(contractAddress, hexToBytes(code)) // setup the contract code + await eeiConstantinople.putContractCode(contractAddress, hexToBytes(code)) // setup the contract code const runCallArgs = { caller, // call address @@ -152,15 +156,15 @@ tape('Byzantium cannot access Constantinople opcodes', async (t) => { tape('Ensure that Istanbul sstoreCleanRefundEIP2200 gas is applied correctly', async (t) => { // setup the accounts for this test - const caller = new Address(Buffer.from('00000000000000000000000000000000000000ee', 'hex')) // caller address - const address = new Address(Buffer.from('00000000000000000000000000000000000000ff', 'hex')) + const caller = new Address(hexToBytes('00000000000000000000000000000000000000ee')) // caller address + const address = new Address(hexToBytes('00000000000000000000000000000000000000ff')) // setup the vm const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Istanbul }) const eei = await getEEI() const evm = await EVM.create({ common, eei }) const code = '61000260005561000160005500' /* - idea: store the original value in the storage slot, except it is now a 1-length buffer instead of a 32-length buffer + idea: store the original value in the storage slot, except it is now a 1-length Uint8Array instead of a 32-length Uint8Array code: PUSH2 0x0002 PUSH1 0x00 @@ -180,12 +184,8 @@ tape('Ensure that Istanbul sstoreCleanRefundEIP2200 gas is applied correctly', a */ - await eei.putContractCode(address, Buffer.from(code, 'hex')) - await eei.putContractStorage( - address, - Buffer.alloc(32, 0), - Buffer.from('00'.repeat(31) + '01', 'hex') - ) + await eei.putContractCode(address, hexToBytes(code)) + await eei.putContractStorage(address, new Uint8Array(32), hexToBytes('00'.repeat(31) + '01')) // setup the call arguments const runCallArgs = { @@ -204,8 +204,8 @@ tape('Ensure that Istanbul sstoreCleanRefundEIP2200 gas is applied correctly', a tape('ensure correct gas for pre-constantinople sstore', async (t) => { // setup the accounts for this test - const caller = new Address(Buffer.from('00000000000000000000000000000000000000ee', 'hex')) // caller address - const address = new Address(Buffer.from('00000000000000000000000000000000000000ff', 'hex')) + const caller = new Address(hexToBytes('00000000000000000000000000000000000000ee')) // caller address + const address = new Address(hexToBytes('00000000000000000000000000000000000000ff')) // setup the vm const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Chainstart }) const eei = await getEEI() @@ -213,7 +213,7 @@ tape('ensure correct gas for pre-constantinople sstore', async (t) => { // push 1 push 0 sstore stop const code = '600160015500' - await eei.putContractCode(address, Buffer.from(code, 'hex')) + await eei.putContractCode(address, hexToBytes(code)) // setup the call arguments const runCallArgs = { @@ -232,8 +232,8 @@ tape('ensure correct gas for pre-constantinople sstore', async (t) => { tape('ensure correct gas for calling non-existent accounts in homestead', async (t) => { // setup the accounts for this test - const caller = new Address(Buffer.from('00000000000000000000000000000000000000ee', 'hex')) // caller address - const address = new Address(Buffer.from('00000000000000000000000000000000000000ff', 'hex')) + const caller = new Address(hexToBytes('00000000000000000000000000000000000000ee')) // caller address + const address = new Address(hexToBytes('00000000000000000000000000000000000000ff')) // setup the vm const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Homestead }) const eei = await getEEI() @@ -241,7 +241,7 @@ tape('ensure correct gas for calling non-existent accounts in homestead', async // code to call 0x00..00dd, which does not exist const code = '6000600060006000600060DD61FFFF5A03F100' - await eei.putContractCode(address, Buffer.from(code, 'hex')) + await eei.putContractCode(address, hexToBytes(code)) // setup the call arguments const runCallArgs = { @@ -264,8 +264,8 @@ tape( 'ensure callcode goes OOG if the gas argument is more than the gas left in the homestead fork', async (t) => { // setup the accounts for this test - const caller = new Address(Buffer.from('00000000000000000000000000000000000000ee', 'hex')) // caller address - const address = new Address(Buffer.from('00000000000000000000000000000000000000ff', 'hex')) + const caller = new Address(hexToBytes('00000000000000000000000000000000000000ee')) // caller address + const address = new Address(hexToBytes('00000000000000000000000000000000000000ff')) // setup the vm const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Homestead }) const eei = await getEEI() @@ -274,7 +274,7 @@ tape( // but using too much memory const code = '61FFFF60FF60006000600060EE6000F200' - await eei.putContractCode(address, Buffer.from(code, 'hex')) + await eei.putContractCode(address, hexToBytes(code)) // setup the call arguments const runCallArgs = { @@ -295,8 +295,8 @@ tape( tape('ensure selfdestruct pays for creating new accounts', async (t) => { // setup the accounts for this test - const caller = new Address(Buffer.from('00000000000000000000000000000000000000ee', 'hex')) // caller address - const address = new Address(Buffer.from('00000000000000000000000000000000000000ff', 'hex')) + const caller = new Address(hexToBytes('00000000000000000000000000000000000000ee')) // caller address + const address = new Address(hexToBytes('00000000000000000000000000000000000000ff')) // setup the vm const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.TangerineWhistle }) const eei = await getEEI() @@ -306,7 +306,7 @@ tape('ensure selfdestruct pays for creating new accounts', async (t) => { // this should thus go OOG const code = '60FEFF' - await eei.putContractCode(address, Buffer.from(code, 'hex')) + await eei.putContractCode(address, hexToBytes(code)) // setup the call arguments const runCallArgs = { @@ -326,8 +326,8 @@ tape('ensure selfdestruct pays for creating new accounts', async (t) => { tape('ensure that sstores pay for the right gas costs pre-byzantium', async (t) => { // setup the accounts for this test - const caller = new Address(Buffer.from('00000000000000000000000000000000000000ee', 'hex')) // caller address - const address = new Address(Buffer.from('00000000000000000000000000000000000000ff', 'hex')) + const caller = new Address(hexToBytes('00000000000000000000000000000000000000ee')) // caller address + const address = new Address(hexToBytes('00000000000000000000000000000000000000ff')) // setup the vm const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Chainstart }) const eei = await getEEI() @@ -337,7 +337,7 @@ tape('ensure that sstores pay for the right gas costs pre-byzantium', async (t) // this should thus go OOG const code = '3460005500' - await eei.putContractCode(address, Buffer.from(code, 'hex')) + await eei.putContractCode(address, hexToBytes(code)) const account = await eei.getAccount(caller) account.balance = BigInt(100) @@ -395,10 +395,10 @@ tape( 'Ensure that contracts cannot exceed nonce of MAX_UINT64 when creating new contracts (EIP-2681)', async (t) => { // setup the accounts for this test - const caller = new Address(Buffer.from('00000000000000000000000000000000000000ee', 'hex')) // caller address - const address = new Address(Buffer.from('00000000000000000000000000000000000000ff', 'hex')) - const slot = Buffer.from('00'.repeat(32), 'hex') - const emptyBuffer = Buffer.from('') + const caller = new Address(hexToBytes('00000000000000000000000000000000000000ee')) // caller address + const address = new Address(hexToBytes('00000000000000000000000000000000000000ff')) + const slot = hexToBytes('00'.repeat(32)) + const emptyBytes = hexToBytes('') // setup the vm const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.London }) const eei = await getEEI() @@ -416,7 +416,7 @@ tape( STOP */ - await eei.putContractCode(address, Buffer.from(code, 'hex')) + await eei.putContractCode(address, hexToBytes(code)) const account = await eei.getAccount(address) account.nonce = MAX_UINT64 - BigInt(1) @@ -433,14 +433,15 @@ tape( let storage = await eei.getContractStorage(address, slot) // The nonce is MAX_UINT64 - 1, so we are allowed to create a contract (nonce of creating contract is now MAX_UINT64) - t.ok(!storage.equals(emptyBuffer), 'successfully created contract') + t.notDeepEqual(storage, emptyBytes, 'successfully created contract') await evm.runCall(runCallArgs) // The nonce is MAX_UINT64, so we are NOT allowed to create a contract (nonce of creating contract is now MAX_UINT64) storage = await eei.getContractStorage(address, slot) - t.ok( - storage.equals(emptyBuffer), + t.deepEquals( + storage, + emptyBytes, 'failed to create contract; nonce of creating contract is too high (MAX_UINT64)' ) @@ -453,7 +454,7 @@ tape('Ensure that IDENTITY precompile copies the memory', async (t) => { // Exploit post-mortem: https://github.com/ethereum/go-ethereum/blob/master/docs/postmortems/2021-08-22-split-postmortem.md // Permalink: https://github.com/ethereum/go-ethereum/blob/90987db7334c1d10eb866ca550efedb66dea8a20/docs/postmortems/2021-08-22-split-postmortem.md // setup the accounts for this test - const caller = new Address(Buffer.from('1a02a619e51cc5f8a2a61d2a60f6c80476ee8ead', 'hex')) // caller address + const caller = new Address(hexToBytes('1a02a619e51cc5f8a2a61d2a60f6c80476ee8ead')) // caller address // setup the vm const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.London }) const eei = await getEEI() @@ -469,7 +470,7 @@ tape('Ensure that IDENTITY precompile copies the memory', async (t) => { const runCallArgs = { caller, // call address gasLimit: BigInt(150000), - data: Buffer.from(code, 'hex'), + data: hexToBytes(code), gasPrice: BigInt(70000000000), } @@ -480,7 +481,7 @@ tape('Ensure that IDENTITY precompile copies the memory', async (t) => { t.equals(result.createdAddress?.toString(), expectedAddress, 'created address correct') const deployedCode = await eei.getContractCode(result.createdAddress!) - t.equals(deployedCode.toString('hex'), expectedCode, 'deployed code correct') + t.equals(bytesToHex(deployedCode), expectedCode, 'deployed code correct') t.end() }) @@ -514,13 +515,10 @@ tape('runCall() -> skipBalance behavior', async (t) => { const evm = await EVM.create({ common, eei }) // runCall against a contract to reach `_reduceSenderBalance` - const contractCode = Buffer.from('00', 'hex') // 00: STOP + const contractCode = hexToBytes('00') // 00: STOP const contractAddress = Address.fromString('0x000000000000000000000000636F6E7472616374') await eei.putContractCode(contractAddress, contractCode) - const senderKey = Buffer.from( - 'e331b6d69882b4cb4ea581d88e0b604039a3de5967688d3dcffdd2270c0fd109', - 'hex' - ) + const senderKey = hexToBytes('e331b6d69882b4cb4ea581d88e0b604039a3de5967688d3dcffdd2270c0fd109') const sender = Address.fromPrivateKey(senderKey) const runCallArgs = { @@ -554,7 +552,7 @@ tape('runCall() -> skipBalance behavior', async (t) => { tape('runCall() => allows to detect for max code size deposit errors', async (t) => { // setup the accounts for this test - const caller = new Address(Buffer.from('00000000000000000000000000000000000000ee', 'hex')) // caller address + const caller = new Address(hexToBytes('00000000000000000000000000000000000000ee')) // caller address // setup the evm const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Istanbul }) const eei = await getEEI() @@ -567,7 +565,7 @@ tape('runCall() => allows to detect for max code size deposit errors', async (t) // Simple test, PUSH PUSH 0 RETURN // It tries to deploy a contract too large, where the code is all zeros // (since memory which is not allocated/resized to yet is always defaulted to 0) - data: Buffer.from('62FFFFFF6000F3', 'hex'), + data: hexToBytes('62FFFFFF6000F3'), } const result = await evm.runCall(runCallArgs) @@ -591,12 +589,12 @@ tape('runCall() => use DATAHASH opcode from EIP 4844', async (t) => { const runCallArgs: EVMRunCallOpts = { gasLimit: BigInt(0xffffffffff), // calldata -- retrieves the versioned hash at index 0 and returns it from memory - data: Buffer.from('60004960005260206000F3', 'hex'), - versionedHashes: [Buffer.from('ab', 'hex')], + data: hexToBytes('60004960005260206000F3'), + versionedHashes: [hexToBytes('ab')], } const res = await evm.runCall(runCallArgs) t.equal( - unpadBuffer(res.execResult.returnValue).toString('hex'), + bytesToHex(unpadBytes(res.execResult.returnValue)), 'ab', 'retrieved correct versionedHash from runState' ) @@ -605,12 +603,12 @@ tape('runCall() => use DATAHASH opcode from EIP 4844', async (t) => { const runCall2Args: EVMRunCallOpts = { gasLimit: BigInt(0xffffffffff), // calldata -- tries to retrieve the versioned hash at index 1 and return it from memory - data: Buffer.from('60014960005260206000F3', 'hex'), - versionedHashes: [Buffer.from('ab', 'hex')], + data: hexToBytes('60014960005260206000F3'), + versionedHashes: [hexToBytes('ab')], } const res2 = await evm.runCall(runCall2Args) t.equal( - unpadBuffer(res2.execResult.returnValue).toString('hex'), + bytesToHex(unpadBytes(res2.execResult.returnValue)), '', 'retrieved no versionedHash when specified versionedHash does not exist in runState' ) @@ -623,7 +621,7 @@ tape('step event: ensure EVM memory and not internal memory gets reported', asyn const eei = await getEEI() const evm = await EVM.create({ common, eei }) - const contractCode = Buffer.from('600060405200', 'hex') // PUSH 0 PUSH 40 MSTORE STOP + const contractCode = hexToBytes('600060405200') // PUSH 0 PUSH 40 MSTORE STOP const contractAddress = Address.fromString('0x000000000000000000000000636F6E7472616374') await eei.putContractCode(contractAddress, contractCode) diff --git a/packages/evm/test/runCode.spec.ts b/packages/evm/test/runCode.spec.ts index 5e195545f0..93502fe1fd 100644 --- a/packages/evm/test/runCode.spec.ts +++ b/packages/evm/test/runCode.spec.ts @@ -1,3 +1,4 @@ +import { hexToBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' import { EVM } from '../src' @@ -26,7 +27,7 @@ tape('VM.runCode: initial program counter', async (t) => { for (const [i, testData] of testCases.entries()) { const runCodeArgs = { - code: Buffer.from(testData.code.join(''), 'hex'), + code: hexToBytes(testData.code.join('')), pc: testData.pc, gasLimit: BigInt(0xffff), } @@ -62,7 +63,7 @@ tape('VM.runCode: interpreter', (t) => { const INVALID_opcode = 'fe' const runCodeArgs = { - code: Buffer.from(INVALID_opcode, 'hex'), + code: hexToBytes(INVALID_opcode), gasLimit: BigInt(0xffff), } @@ -86,7 +87,7 @@ tape('VM.runCode: interpreter', (t) => { const SSTORE = '55' const runCodeArgs = { - code: Buffer.from([PUSH1, '01', PUSH1, '05', SSTORE].join(''), 'hex'), + code: hexToBytes([PUSH1, '01', PUSH1, '05', SSTORE].join('')), gasLimit: BigInt(0xffff), } diff --git a/packages/evm/test/stack.spec.ts b/packages/evm/test/stack.spec.ts index 580f6fb36b..4ebc724bf3 100644 --- a/packages/evm/test/stack.spec.ts +++ b/packages/evm/test/stack.spec.ts @@ -1,4 +1,5 @@ -import { Account, Address, bigIntToBuffer, setLengthLeft } from '@ethereumjs/util' +import { Account, Address, bigIntToBytes, setLengthLeft } from '@ethereumjs/util' +import { hexToBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' import { EVM } from '../src' @@ -126,13 +127,13 @@ tape('Stack', (t) => { }) t.test('stack items should not change if they are DUPed', async (st) => { - const caller = new Address(Buffer.from('00000000000000000000000000000000000000ee', 'hex')) - const addr = new Address(Buffer.from('00000000000000000000000000000000000000ff', 'hex')) + const caller = new Address(hexToBytes('00000000000000000000000000000000000000ee')) + const addr = new Address(hexToBytes('00000000000000000000000000000000000000ff')) const eei = await getEEI() const evm = await EVM.create({ eei }) const account = createAccount(BigInt(0), BigInt(0)) const code = '60008080808060013382F15060005260206000F3' - const expectedReturnValue = setLengthLeft(bigIntToBuffer(BigInt(0)), 32) + const expectedReturnValue = setLengthLeft(bigIntToBytes(BigInt(0)), 32) /* code: remarks: (top of the stack is at the zero index) PUSH1 0x00 @@ -152,7 +153,7 @@ tape('Stack', (t) => { RETURN stack: [0, 0x20] (we thus return the stack item which was originally pushed as 0, and then DUPed) */ await eei.putAccount(addr, account) - await eei.putContractCode(addr, Buffer.from(code, 'hex')) + await eei.putContractCode(addr, hexToBytes(code)) await eei.putAccount(caller, new Account(BigInt(0), BigInt(0x11))) const runCallArgs = { caller, @@ -163,7 +164,7 @@ tape('Stack', (t) => { try { const res = await evm.runCall(runCallArgs) const executionReturnValue = res.execResult.returnValue - st.assert(executionReturnValue.equals(expectedReturnValue)) + st.deepEquals(executionReturnValue, expectedReturnValue) st.end() } catch (e: any) { st.fail(e.message) diff --git a/packages/evm/test/transientStorage.spec.ts b/packages/evm/test/transientStorage.spec.ts index 2d49cb8639..60e390c259 100644 --- a/packages/evm/test/transientStorage.spec.ts +++ b/packages/evm/test/transientStorage.spec.ts @@ -9,8 +9,8 @@ tape('Transient Storage', (tester) => { const transientStorage = new TransientStorage() const address = Address.fromString('0xff00000000000000000000000000000000000002') - const key = Buffer.alloc(32, 0xff) - const value = Buffer.alloc(32, 0x99) + const key = new Uint8Array(32).fill(0xff) + const value = new Uint8Array(32).fill(0x99) transientStorage.put(address, key, value) const got = transientStorage.get(address, key) @@ -22,17 +22,17 @@ tape('Transient Storage', (tester) => { const transientStorage = new TransientStorage() const address = Address.fromString('0xff00000000000000000000000000000000000002') - const key = Buffer.alloc(32, 0xff) - const value = Buffer.alloc(32, 0x11) + const key = new Uint8Array(32).fill(0xff) + const value = new Uint8Array(32).fill(0x11) // No address set const got = transientStorage.get(address, key) - t.deepEqual(Buffer.alloc(32, 0x00), got) + t.deepEqual(new Uint8Array(32).fill(0x00), got) // Address set, no key set transientStorage.put(address, key, value) - const got2 = transientStorage.get(address, Buffer.alloc(32, 0x22)) - t.deepEqual(Buffer.alloc(32, 0x00), got2) + const got2 = transientStorage.get(address, new Uint8Array(32).fill(0x22)) + t.deepEqual(new Uint8Array(32).fill(0x00), got2) t.end() }) @@ -40,14 +40,14 @@ tape('Transient Storage', (tester) => { const transientStorage = new TransientStorage() const address = Address.fromString('0xff00000000000000000000000000000000000002') - const key = Buffer.alloc(32, 0xff) - const value = Buffer.alloc(32, 0x99) + const key = new Uint8Array(32).fill(0xff) + const value = new Uint8Array(32).fill(0x99) transientStorage.put(address, key, value) transientStorage.checkpoint() - const value2 = Buffer.alloc(32, 0x22) + const value2 = new Uint8Array(32).fill(0x22) transientStorage.put(address, key, value2) const got = transientStorage.get(address, key) t.deepEqual(got, value2) @@ -63,8 +63,8 @@ tape('Transient Storage', (tester) => { const transientStorage = new TransientStorage() const address = Address.fromString('0xff00000000000000000000000000000000000002') - const key = Buffer.alloc(32, 0xff) - const value = Buffer.alloc(32, 0x99) + const key = new Uint8Array(32).fill(0xff) + const value = new Uint8Array(32).fill(0x99) transientStorage.put(address, key, value) @@ -82,11 +82,11 @@ tape('Transient Storage', (tester) => { const address = Address.fromString('0xff00000000000000000000000000000000000002') t.throws(() => { - transientStorage.put(address, Buffer.alloc(10), Buffer.alloc(1)) + transientStorage.put(address, new Uint8Array(10), new Uint8Array(1)) }, /Transient storage key must be 32 bytes long/) t.throws(() => { - transientStorage.put(address, Buffer.alloc(32), Buffer.alloc(33)) + transientStorage.put(address, new Uint8Array(32), new Uint8Array(33)) }, /Transient storage value cannot be longer than 32 bytes/) t.end() @@ -96,14 +96,14 @@ tape('Transient Storage', (tester) => { const transientStorage = new TransientStorage() const address = Address.fromString('0xff00000000000000000000000000000000000002') - const key = Buffer.alloc(32, 0xff) - const value = Buffer.alloc(32, 0x99) + const key = new Uint8Array(32).fill(0xff) + const value = new Uint8Array(32).fill(0x99) transientStorage.put(address, key, value) t.deepEqual( transientStorage.get( Address.fromString('0xff00000000000000000000000000000000000002'), - Buffer.alloc(32, 0xff) + new Uint8Array(32).fill(0xff) ), value ) @@ -114,10 +114,10 @@ tape('Transient Storage', (tester) => { const transientStorage = new TransientStorage() const address = Address.fromString('0xff00000000000000000000000000000000000002') - const key = Buffer.alloc(32, 0xff) - const value1 = Buffer.alloc(32, 0x01) - const value2 = Buffer.alloc(32, 0x02) - const value3 = Buffer.alloc(32, 0x03) + const key = new Uint8Array(32).fill(0xff) + const value1 = new Uint8Array(32).fill(0x01) + const value2 = new Uint8Array(32).fill(0x02) + const value3 = new Uint8Array(32).fill(0x03) transientStorage.put(address, key, value1) transientStorage.checkpoint() @@ -133,11 +133,11 @@ tape('Transient Storage', (tester) => { const transientStorage = new TransientStorage() const address = Address.fromString('0xff00000000000000000000000000000000000002') - const key = Buffer.alloc(32, 0xff) - const value0 = Buffer.alloc(32, 0x00) - const value1 = Buffer.alloc(32, 0x01) - const value2 = Buffer.alloc(32, 0x02) - const value3 = Buffer.alloc(32, 0x03) + const key = new Uint8Array(32).fill(0xff) + const value0 = new Uint8Array(32).fill(0x00) + const value1 = new Uint8Array(32).fill(0x01) + const value2 = new Uint8Array(32).fill(0x02) + const value3 = new Uint8Array(32).fill(0x03) transientStorage.put(address, key, value1) transientStorage.checkpoint() @@ -165,10 +165,10 @@ tape('Transient Storage', (tester) => { const transientStorage = new TransientStorage() const address = Address.fromString('0xff00000000000000000000000000000000000002') - const key = Buffer.alloc(32, 0xff) - const value1 = Buffer.alloc(32, 0x01) - const value2 = Buffer.alloc(32, 0x02) - const value3 = Buffer.alloc(32, 0x03) + const key = new Uint8Array(32).fill(0xff) + const value1 = new Uint8Array(32).fill(0x01) + const value2 = new Uint8Array(32).fill(0x02) + const value3 = new Uint8Array(32).fill(0x03) transientStorage.put(address, key, value1) transientStorage.checkpoint() diff --git a/packages/statemanager/src/baseStateManager.ts b/packages/statemanager/src/baseStateManager.ts index 8bc471fcab..778be20e1c 100644 --- a/packages/statemanager/src/baseStateManager.ts +++ b/packages/statemanager/src/baseStateManager.ts @@ -99,9 +99,9 @@ export abstract class BaseStateManager { return account.isEmpty() } - abstract putContractCode(address: Address, value: Buffer): Promise - abstract getContractStorage(address: Address, key: Buffer): Promise - abstract putContractStorage(address: Address, key: Buffer, value: Buffer): Promise + abstract putContractCode(address: Address, value: Uint8Array): Promise + abstract getContractStorage(address: Address, key: Uint8Array): Promise + abstract putContractStorage(address: Address, key: Uint8Array, value: Uint8Array): Promise /** * Checkpoints the current state of the StateManager instance. diff --git a/packages/statemanager/src/cache.ts b/packages/statemanager/src/cache.ts index fc56f8140e..8cd0607d3e 100644 --- a/packages/statemanager/src/cache.ts +++ b/packages/statemanager/src/cache.ts @@ -1,12 +1,12 @@ -import { Account } from '@ethereumjs/util' +import { Account, bytesToHex, hexStringToBytes } from '@ethereumjs/util' import { OrderedMap } from 'js-sdsl' import type { Address } from '@ethereumjs/util' import type { OrderedMapIterator } from 'js-sdsl' export type getCb = (address: Address) => Promise -export type putCb = (keyBuf: Buffer, accountRlp: Buffer) => Promise -export type deleteCb = (keyBuf: Buffer) => Promise +export type putCb = (keyBuf: Uint8Array, accountRlp: Uint8Array) => Promise +export type deleteCb = (keyBuf: Uint8Array) => Promise export interface CacheOpts { getCb: getCb @@ -59,7 +59,7 @@ export class Cache { * @param key - Address of account */ lookup(key: Address): Account | undefined { - const keyStr = key.buf.toString('hex') + const keyStr = bytesToHex(key.bytes) const it = this._cache.find(keyStr) if (!it.equals(this._cacheEnd)) { @@ -76,7 +76,7 @@ export class Cache { * @param key - trie key to lookup */ keyIsDeleted(key: Address): boolean { - const keyStr = key.buf.toString('hex') + const keyStr = bytesToHex(key.bytes) const it = this._cache.find(keyStr) if (!it.equals(this._cacheEnd)) { return it.pointer[1].deleted @@ -116,7 +116,7 @@ export class Cache { const value = it.pointer[1] if (value.modified === true) { value.modified = false - const keyBuf = Buffer.from(it.pointer[0], 'hex') + const keyBuf = hexStringToBytes(it.pointer[0]) if (value.deleted === false) { const accountRlp = value.val await this._putCb(keyBuf, accountRlp) @@ -185,7 +185,7 @@ export class Cache { deleted: boolean, virtual = false ): void { - const keyHex = key.buf.toString('hex') + const keyHex = bytesToHex(key.bytes) const val = value.serialize() this._cache.setElement(keyHex, { val, modified, deleted, virtual }) } diff --git a/packages/statemanager/src/ethersStateManager.ts b/packages/statemanager/src/ethersStateManager.ts index a9d7c32a3e..80c825bf9d 100644 --- a/packages/statemanager/src/ethersStateManager.ts +++ b/packages/statemanager/src/ethersStateManager.ts @@ -1,12 +1,5 @@ import { Trie } from '@ethereumjs/trie' -import { - Account, - bigIntToHex, - bufferToBigInt, - bufferToHex, - setLengthLeft, - toBuffer, -} from '@ethereumjs/util' +import { Account, bigIntToHex, bytesToBigInt, bytesToHex, toBytes } from '@ethereumjs/util' import { debug } from 'debug' import { keccak256 } from 'ethereum-cryptography/keccak' import { ethers } from 'ethers' @@ -29,8 +22,8 @@ export interface EthersStateManagerOpts { export class EthersStateManager extends BaseStateManager implements StateManager { private provider: ethers.providers.StaticJsonRpcProvider | ethers.providers.JsonRpcProvider - private contractCache: Map - private storageCache: Map> + private contractCache: Map + private storageCache: Map> private blockTag: string _cache: Cache @@ -55,7 +48,7 @@ export class EthersStateManager extends BaseStateManager implements StateManager const putCb: putCb = async (_keyBuf, _accountRlp) => { return Promise.resolve() } - const deleteCb = async (_keyBuf: Buffer) => { + const deleteCb = async (_keyBuf: Uint8Array) => { return Promise.resolve() } this._cache = new Cache({ getCb, putCb, deleteCb }) @@ -95,16 +88,16 @@ export class EthersStateManager extends BaseStateManager implements StateManager /** * Gets the code corresponding to the provided `address`. * @param address - Address to get the `code` for - * @returns {Promise} - Resolves with the code corresponding to the provided address. - * Returns an empty `Buffer` if the account has no associated code. + * @returns {Promise} - Resolves with the code corresponding to the provided address. + * Returns an empty `Uint8Array` if the account has no associated code. */ - async getContractCode(address: Address): Promise { - let codeBuffer = this.contractCache.get(address.toString()) - if (codeBuffer !== undefined) return codeBuffer + async getContractCode(address: Address): Promise { + let codeBytes = this.contractCache.get(address.toString()) + if (codeBytes !== undefined) return codeBytes const code = await this.provider.getCode(address.toString(), this.blockTag) - codeBuffer = toBuffer(code) - this.contractCache.set(address.toString(), codeBuffer) - return codeBuffer + codeBytes = toBytes(code) + this.contractCache.set(address.toString(), codeBytes) + return codeBytes } /** @@ -113,7 +106,7 @@ export class EthersStateManager extends BaseStateManager implements StateManager * @param address - Address of the `account` to add the `code` for * @param value - The value of the `code` */ - async putContractCode(address: Address, value: Buffer): Promise { + async putContractCode(address: Address, value: Uint8Array): Promise { // Store contract code in the cache this.contractCache.set(address.toString(), value) } @@ -123,18 +116,18 @@ export class EthersStateManager extends BaseStateManager implements StateManager * the shortest representation of the stored value. * @param address - Address of the account to get the storage for * @param key - Key in the account's storage to get the value for. Must be 32 bytes long. - * @returns {Buffer} - The storage value for the account + * @returns {Uint8Array} - The storage value for the account * corresponding to the provided address at the provided key. - * If this does not exist an empty `Buffer` is returned. + * If this does not exist an empty `Uint8Array` is returned. */ - async getContractStorage(address: Address, key: Buffer): Promise { + async getContractStorage(address: Address, key: Uint8Array): Promise { // Check storage slot in cache - const accountStorage: Map | undefined = this.storageCache.get( + const accountStorage: Map | undefined = this.storageCache.get( address.toString() ) - let storage: Buffer | string | undefined + let storage: Uint8Array | string | undefined if (accountStorage !== undefined) { - storage = accountStorage.get(key.toString('hex')) + storage = accountStorage.get(bytesToHex(key)) if (storage !== undefined) { return storage } @@ -143,10 +136,10 @@ export class EthersStateManager extends BaseStateManager implements StateManager // Retrieve storage slot from provider if not found in cache storage = await this.provider.getStorageAt( address.toString(), - bufferToBigInt(key), + bytesToBigInt(key), this.blockTag ) - const value = toBuffer(storage) + const value = toBytes(storage) await this.putContractStorage(address, key, value) return value @@ -161,13 +154,13 @@ export class EthersStateManager extends BaseStateManager implements StateManager * Cannot be more than 32 bytes. Leading zeros are stripped. * If it is empty or filled with zeros, deletes the value. */ - async putContractStorage(address: Address, key: Buffer, value: Buffer): Promise { + async putContractStorage(address: Address, key: Uint8Array, value: Uint8Array): Promise { let accountStorage = this.storageCache.get(address.toString()) if (accountStorage === undefined) { - this.storageCache.set(address.toString(), new Map()) + this.storageCache.set(address.toString(), new Map()) accountStorage = this.storageCache.get(address.toString()) } - accountStorage?.set(key.toString('hex'), value) + accountStorage?.set(bytesToHex(key), value) } /** @@ -190,7 +183,7 @@ export class EthersStateManager extends BaseStateManager implements StateManager const dump: StorageDump = {} if (addressStorage !== undefined) { for (const slot of addressStorage) { - dump[slot[0]] = bufferToHex(slot[1]) + dump[slot[0]] = bytesToHex(slot[1]) } } return Promise.resolve(dump) @@ -208,14 +201,10 @@ export class EthersStateManager extends BaseStateManager implements StateManager // Get merkle proof for `address` from provider const proof = await this.provider.send('eth_getProof', [address.toString(), [], this.blockTag]) - const proofBuf = proof.accountProof.map((proofNode: string) => toBuffer(proofNode)) + const proofBuf = proof.accountProof.map((proofNode: string) => toBytes(proofNode)) const trie = new Trie({ useKeyHashing: true }) - const verified = await trie.verifyProof( - Buffer.from(keccak256(proofBuf[0])), - address.buf, - proofBuf - ) + const verified = await trie.verifyProof(keccak256(proofBuf[0]), address.bytes, proofBuf) // if not verified (i.e. verifyProof returns null), account does not exist return verified === null ? false : true } @@ -223,8 +212,8 @@ export class EthersStateManager extends BaseStateManager implements StateManager /** * Gets the code corresponding to the provided `address`. * @param address - Address to get the `code` for - * @returns {Promise} - Resolves with the code corresponding to the provided address. - * Returns an empty `Buffer` if the account has no associated code. + * @returns {Promise} - Resolves with the code corresponding to the provided address. + * Returns an empty `Uint8Array` if the account has no associated code. */ async getAccount(address: Address): Promise { const account = this._cache.getOrLoad(address) @@ -246,8 +235,8 @@ export class EthersStateManager extends BaseStateManager implements StateManager const account = Account.fromAccountData({ balance: BigInt(accountData.balance), nonce: BigInt(accountData.nonce), - codeHash: toBuffer(accountData.codeHash), - storageRoot: toBuffer(accountData.storageHash), + codeHash: toBytes(accountData.codeHash), + storageRoot: toBytes(accountData.storageHash), }) return account } @@ -267,10 +256,10 @@ export class EthersStateManager extends BaseStateManager implements StateManager * @param storageSlots storage slots to get proof of * @returns an EIP-1186 formatted proof */ - async getProof(address: Address, storageSlots: Buffer[] = []): Promise { + async getProof(address: Address, storageSlots: Uint8Array[] = []): Promise { const proof = await this.provider.send('eth_getProof', [ address.toString(), - [storageSlots.map((slot) => bufferToHex(slot))], + [storageSlots.map((slot) => bytesToHex(slot))], this.blockTag, ]) @@ -318,13 +307,13 @@ export class EthersStateManager extends BaseStateManager implements StateManager * @deprecated This method is not used by the Ethers State Manager and is a stub required by the State Manager interface */ getStateRoot = async () => { - return setLengthLeft(Buffer.from([]), 32) + return new Uint8Array(32) } /** * @deprecated This method is not used by the Ethers State Manager and is a stub required by the State Manager interface */ - setStateRoot = async (_root: Buffer) => {} + setStateRoot = async (_root: Uint8Array) => {} /** * @deprecated This method is not used by the Ethers State Manager and is a stub required by the State Manager interface diff --git a/packages/statemanager/src/interface.ts b/packages/statemanager/src/interface.ts index 28614d1431..b7353515cd 100644 --- a/packages/statemanager/src/interface.ts +++ b/packages/statemanager/src/interface.ts @@ -17,19 +17,19 @@ export interface StateAccess { accountIsEmpty(address: Address): Promise deleteAccount(address: Address): Promise modifyAccountFields(address: Address, accountFields: AccountFields): Promise - putContractCode(address: Address, value: Buffer): Promise - getContractCode(address: Address): Promise - getContractStorage(address: Address, key: Buffer): Promise - putContractStorage(address: Address, key: Buffer, value: Buffer): Promise + putContractCode(address: Address, value: Uint8Array): Promise + getContractCode(address: Address): Promise + getContractStorage(address: Address, key: Uint8Array): Promise + putContractStorage(address: Address, key: Uint8Array, value: Uint8Array): Promise clearContractStorage(address: Address): Promise checkpoint(): Promise commit(): Promise revert(): Promise - getStateRoot(): Promise - setStateRoot(stateRoot: Buffer): Promise - getProof?(address: Address, storageSlots: Buffer[]): Promise + getStateRoot(): Promise + setStateRoot(stateRoot: Uint8Array): Promise + getProof?(address: Address, storageSlots: Uint8Array[]): Promise verifyProof?(proof: Proof): Promise - hasStateRoot(root: Buffer): Promise + hasStateRoot(root: Uint8Array): Promise } export interface StateManager extends StateAccess { diff --git a/packages/statemanager/src/stateManager.ts b/packages/statemanager/src/stateManager.ts index 548e754ab7..ff7f4bab35 100644 --- a/packages/statemanager/src/stateManager.ts +++ b/packages/statemanager/src/stateManager.ts @@ -5,11 +5,15 @@ import { KECCAK256_NULL, KECCAK256_RLP, bigIntToHex, - bufferToHex, + bytesToHex, + bytesToPrefixedHexString, + concatBytes, + equalsBytes, + hexStringToBytes, setLengthLeft, short, - toBuffer, - unpadBuffer, + unpadBytes, + utf8ToBytes, } from '@ethereumjs/util' import { keccak256 } from 'ethereum-cryptography/keccak' @@ -44,7 +48,7 @@ export type Proof = { * will be the same as the hash of the empty trie which leads to * misbehaviour in the underlying trie library. */ -export const CODEHASH_PREFIX = Buffer.from('c') +export const CODEHASH_PREFIX = utf8ToBytes('c') /** * Options for constructing a {@link StateManager}. @@ -97,14 +101,14 @@ export class DefaultStateManager extends BaseStateManager implements StateManage * desired backend. */ const getCb: getCb = async (address) => { - const rlp = await this._trie.get(address.buf) + const rlp = await this._trie.get(address.bytes) return rlp ? Account.fromRlpSerializedAccount(rlp) : undefined } const putCb: putCb = async (keyBuf, accountRlp) => { const trie = this._trie await trie.put(keyBuf, accountRlp) } - const deleteCb = async (keyBuf: Buffer) => { + const deleteCb = async (keyBuf: Uint8Array) => { const trie = this._trie await trie.del(keyBuf) } @@ -128,14 +132,14 @@ export class DefaultStateManager extends BaseStateManager implements StateManage * @param address - Address of the `account` to add the `code` for * @param value - The value of the `code` */ - async putContractCode(address: Address, value: Buffer): Promise { - const codeHash = Buffer.from(keccak256(value)) + async putContractCode(address: Address, value: Uint8Array): Promise { + const codeHash = keccak256(value) - if (codeHash.equals(KECCAK256_NULL)) { + if (equalsBytes(codeHash, KECCAK256_NULL)) { return } - const key = this._prefixCodeHashes ? Buffer.concat([CODEHASH_PREFIX, codeHash]) : codeHash + const key = this._prefixCodeHashes ? concatBytes(CODEHASH_PREFIX, codeHash) : codeHash // @ts-expect-error await this._trie._db.put(key, value) @@ -148,20 +152,20 @@ export class DefaultStateManager extends BaseStateManager implements StateManage /** * Gets the code corresponding to the provided `address`. * @param address - Address to get the `code` for - * @returns {Promise} - Resolves with the code corresponding to the provided address. - * Returns an empty `Buffer` if the account has no associated code. + * @returns {Promise} - Resolves with the code corresponding to the provided address. + * Returns an empty `Uint8Array` if the account has no associated code. */ - async getContractCode(address: Address): Promise { + async getContractCode(address: Address): Promise { const account = await this.getAccount(address) if (!account.isContract()) { - return Buffer.alloc(0) + return new Uint8Array(0) } const key = this._prefixCodeHashes - ? Buffer.concat([CODEHASH_PREFIX, account.codeHash]) + ? concatBytes(CODEHASH_PREFIX, account.codeHash) : account.codeHash // @ts-expect-error const code = await this._trie._db.get(key) - return code ?? Buffer.alloc(0) + return code ?? new Uint8Array(0) } /** @@ -185,7 +189,7 @@ export class DefaultStateManager extends BaseStateManager implements StateManage */ async _getStorageTrie(address: Address): Promise { // from storage cache - const addressHex = address.buf.toString('hex') + const addressHex = bytesToHex(address.bytes) let storageTrie = this._storageTries[addressHex] if (storageTrie === undefined || storageTrie === null) { // lookup from state @@ -199,18 +203,18 @@ export class DefaultStateManager extends BaseStateManager implements StateManage * the shortest representation of the stored value. * @param address - Address of the account to get the storage for * @param key - Key in the account's storage to get the value for. Must be 32 bytes long. - * @returns {Promise} - The storage value for the account + * @returns {Promise} - The storage value for the account * corresponding to the provided address at the provided key. - * If this does not exist an empty `Buffer` is returned. + * If this does not exist an empty `Uint8Array` is returned. */ - async getContractStorage(address: Address, key: Buffer): Promise { + async getContractStorage(address: Address, key: Uint8Array): Promise { if (key.length !== 32) { throw new Error('Storage key must be 32 bytes long') } const trie = await this._getStorageTrie(address) const value = await trie.get(key) - const decoded = Buffer.from(RLP.decode(Uint8Array.from(value ?? [])) as Uint8Array) + const decoded = RLP.decode(value ?? new Uint8Array(0)) as Uint8Array return decoded } @@ -230,7 +234,7 @@ export class DefaultStateManager extends BaseStateManager implements StateManage modifyTrie(storageTrie, async () => { // update storage cache - const addressHex = address.buf.toString('hex') + const addressHex = bytesToHex(address.bytes) this._storageTries[addressHex] = storageTrie // update contract storageRoot @@ -250,7 +254,7 @@ export class DefaultStateManager extends BaseStateManager implements StateManage * @param key - Key to set the value at. Must be 32 bytes long. * @param value - Value to set at `key` for account corresponding to `address`. Cannot be more than 32 bytes. Leading zeros are stripped. If it is a empty or filled with zeros, deletes the value. */ - async putContractStorage(address: Address, key: Buffer, value: Buffer): Promise { + async putContractStorage(address: Address, key: Uint8Array, value: Uint8Array): Promise { if (key.length !== 32) { throw new Error('Storage key must be 32 bytes long') } @@ -259,12 +263,12 @@ export class DefaultStateManager extends BaseStateManager implements StateManage throw new Error('Storage value cannot be longer than 32 bytes') } - value = unpadBuffer(value) + value = unpadBytes(value) await this._modifyContractStorage(address, async (storageTrie, done) => { - if (Buffer.isBuffer(value) && value.length) { + if (value instanceof Uint8Array && value.length) { // format input - const encodedValue = Buffer.from(RLP.encode(Uint8Array.from(value))) + const encodedValue = RLP.encode(value) if (this.DEBUG) { this._debug(`Update contract storage for account ${address} to ${short(value)}`) } @@ -327,22 +331,24 @@ export class DefaultStateManager extends BaseStateManager implements StateManage * @param address address to get proof of * @param storageSlots storage slots to get proof of */ - async getProof(address: Address, storageSlots: Buffer[] = []): Promise { + async getProof(address: Address, storageSlots: Uint8Array[] = []): Promise { const account = await this.getAccount(address) - const accountProof: PrefixedHexString[] = (await this._trie.createProof(address.buf)).map((p) => - bufferToHex(p) + const accountProof: PrefixedHexString[] = (await this._trie.createProof(address.bytes)).map( + (p) => bytesToPrefixedHexString(p) ) const storageProof: StorageProof[] = [] const storageTrie = await this._getStorageTrie(address) for (const storageKey of storageSlots) { - const proof = (await storageTrie.createProof(storageKey)).map((p) => bufferToHex(p)) - let value = bufferToHex(await this.getContractStorage(address, storageKey)) + const proof = (await storageTrie.createProof(storageKey)).map((p) => + bytesToPrefixedHexString(p) + ) + let value = bytesToPrefixedHexString(await this.getContractStorage(address, storageKey)) if (value === '0x') { value = '0x0' } const proofItem: StorageProof = { - key: bufferToHex(storageKey), + key: bytesToPrefixedHexString(storageKey), value, proof, } @@ -352,9 +358,9 @@ export class DefaultStateManager extends BaseStateManager implements StateManage const returnValue: Proof = { address: address.toString(), balance: bigIntToHex(account.balance), - codeHash: bufferToHex(account.codeHash), + codeHash: bytesToPrefixedHexString(account.codeHash), nonce: bigIntToHex(account.nonce), - storageHash: bufferToHex(account.storageRoot), + storageHash: bytesToPrefixedHexString(account.storageRoot), accountProof, storageProof, } @@ -366,10 +372,10 @@ export class DefaultStateManager extends BaseStateManager implements StateManage * @param proof the proof to prove */ async verifyProof(proof: Proof): Promise { - const rootHash = Buffer.from(keccak256(toBuffer(proof.accountProof[0]))) - const key = toBuffer(proof.address) + const rootHash = keccak256(hexStringToBytes(proof.accountProof[0])) + const key = hexStringToBytes(proof.address) const accountProof = proof.accountProof.map((rlpString: PrefixedHexString) => - toBuffer(rlpString) + hexStringToBytes(rlpString) ) // This returns the account if the proof is valid. @@ -378,22 +384,23 @@ export class DefaultStateManager extends BaseStateManager implements StateManage if (value === null) { // Verify that the account is empty in the proof. - const emptyBuffer = Buffer.from('') + const emptyBytes = new Uint8Array(0) const notEmptyErrorMsg = 'Invalid proof provided: account is not empty' - const nonce = unpadBuffer(toBuffer(proof.nonce)) - if (!nonce.equals(emptyBuffer)) { + + const nonce = unpadBytes(hexStringToBytes(proof.nonce)) + if (!equalsBytes(nonce, emptyBytes)) { throw new Error(`${notEmptyErrorMsg} (nonce is not zero)`) } - const balance = unpadBuffer(toBuffer(proof.balance)) - if (!balance.equals(emptyBuffer)) { + const balance = unpadBytes(hexStringToBytes(proof.balance)) + if (!equalsBytes(balance, emptyBytes)) { throw new Error(`${notEmptyErrorMsg} (balance is not zero)`) } - const storageHash = toBuffer(proof.storageHash) - if (!storageHash.equals(KECCAK256_RLP)) { + const storageHash = hexStringToBytes(proof.storageHash) + if (!equalsBytes(storageHash, KECCAK256_RLP)) { throw new Error(`${notEmptyErrorMsg} (storageHash does not equal KECCAK256_RLP)`) } - const codeHash = toBuffer(proof.codeHash) - if (!codeHash.equals(KECCAK256_NULL)) { + const codeHash = hexStringToBytes(proof.codeHash) + if (!equalsBytes(codeHash, KECCAK256_NULL)) { throw new Error(`${notEmptyErrorMsg} (codeHash does not equal KECCAK256_NULL)`) } } else { @@ -406,30 +413,30 @@ export class DefaultStateManager extends BaseStateManager implements StateManage if (balance !== BigInt(proof.balance)) { throw new Error(`${invalidErrorMsg} balance does not match`) } - if (!storageRoot.equals(toBuffer(proof.storageHash))) { + if (!equalsBytes(storageRoot, hexStringToBytes(proof.storageHash))) { throw new Error(`${invalidErrorMsg} storageHash does not match`) } - if (!codeHash.equals(toBuffer(proof.codeHash))) { + if (!equalsBytes(codeHash, hexStringToBytes(proof.codeHash))) { throw new Error(`${invalidErrorMsg} codeHash does not match`) } } - const storageRoot = toBuffer(proof.storageHash) + const storageRoot = hexStringToBytes(proof.storageHash) for (const stProof of proof.storageProof) { - const storageProof = stProof.proof.map((value: PrefixedHexString) => toBuffer(value)) - const storageValue = setLengthLeft(toBuffer(stProof.value), 32) - const storageKey = toBuffer(stProof.key) + const storageProof = stProof.proof.map((value: PrefixedHexString) => hexStringToBytes(value)) + const storageValue = setLengthLeft(hexStringToBytes(stProof.value), 32) + const storageKey = hexStringToBytes(stProof.key) const proofValue = await new Trie({ useKeyHashing: true }).verifyProof( storageRoot, storageKey, storageProof ) const reportedValue = setLengthLeft( - Buffer.from(RLP.decode(Uint8Array.from((proofValue as Buffer) ?? [])) as Uint8Array), + RLP.decode(proofValue ?? new Uint8Array(0)) as Uint8Array, 32 ) - if (!reportedValue.equals(storageValue)) { + if (!equalsBytes(reportedValue, storageValue)) { throw new Error('Reported trie value does not match storage') } } @@ -440,9 +447,9 @@ export class DefaultStateManager extends BaseStateManager implements StateManage * Gets the state-root of the Merkle-Patricia trie representation * of the state of this StateManager. Will error if there are uncommitted * checkpoints on the instance. - * @returns {Promise} - Returns the state-root of the `StateManager` + * @returns {Promise} - Returns the state-root of the `StateManager` */ - async getStateRoot(): Promise { + async getStateRoot(): Promise { await this._cache.flush() return this._trie.root() } @@ -454,10 +461,10 @@ export class DefaultStateManager extends BaseStateManager implements StateManage * the state trie. * @param stateRoot - The state-root to reset the instance to */ - async setStateRoot(stateRoot: Buffer): Promise { + async setStateRoot(stateRoot: Uint8Array): Promise { await this._cache.flush() - if (!stateRoot.equals(this._trie.EMPTY_TRIE_ROOT)) { + if (!equalsBytes(stateRoot, this._trie.EMPTY_TRIE_ROOT)) { const hasRoot = await this._trie.checkRoot(stateRoot) if (!hasRoot) { throw new Error('State trie does not contain state root') @@ -484,7 +491,7 @@ export class DefaultStateManager extends BaseStateManager implements StateManage const stream = trie.createReadStream() stream.on('data', (val: any) => { - storage[val.key.toString('hex')] = val.value.toString('hex') + storage[bytesToHex(val.key)] = bytesToHex(val.value) }) stream.on('end', () => { resolve(storage) @@ -499,7 +506,7 @@ export class DefaultStateManager extends BaseStateManager implements StateManage /** * Checks whether there is a state corresponding to a stateRoot */ - async hasStateRoot(root: Buffer): Promise { + async hasStateRoot(root: Uint8Array): Promise { return this._trie.checkRoot(root) } @@ -517,7 +524,7 @@ export class DefaultStateManager extends BaseStateManager implements StateManage ) { return true } - if (await this._trie.get(address.buf)) { + if (await this._trie.get(address.bytes)) { return true } return false diff --git a/packages/statemanager/test/cache.spec.ts b/packages/statemanager/test/cache.spec.ts index 20a58fadf6..ff761023d4 100644 --- a/packages/statemanager/test/cache.spec.ts +++ b/packages/statemanager/test/cache.spec.ts @@ -1,5 +1,5 @@ import { Trie } from '@ethereumjs/trie' -import { Account, Address } from '@ethereumjs/util' +import { Account, Address, hexStringToBytes } from '@ethereumjs/util' import * as tape from 'tape' import { Cache } from '../src/cache' @@ -13,14 +13,14 @@ tape('cache initialization', (t) => { const trie = new Trie({ useKeyHashing: true }) const getCb: getCb = async (address) => { const innerTrie = trie - const rlp = await innerTrie.get(address.buf) + const rlp = await innerTrie.get(address.bytes) return rlp ? Account.fromRlpSerializedAccount(rlp) : undefined } const putCb: putCb = async (keyBuf, accountRlp) => { const innerTrie = trie await innerTrie.put(keyBuf, accountRlp) } - const deleteCb = async (keyBuf: Buffer) => { + const deleteCb = async (keyBuf: Uint8Array) => { const innerTrie = trie await innerTrie.del(keyBuf) } @@ -35,20 +35,20 @@ tape('cache put and get account', (t) => { const trie = new Trie({ useKeyHashing: true }) const getCb: getCb = async (address) => { const innerTrie = trie - const rlp = await innerTrie.get(address.buf) + const rlp = await innerTrie.get(address.bytes) return rlp ? Account.fromRlpSerializedAccount(rlp) : undefined } const putCb: putCb = async (keyBuf, accountRlp) => { const innerTrie = trie await innerTrie.put(keyBuf, accountRlp) } - const deleteCb = async (keyBuf: Buffer) => { + const deleteCb = async (keyBuf: Uint8Array) => { const innerTrie = trie await innerTrie.del(keyBuf) } const cache = new Cache({ getCb, putCb, deleteCb }) - const addr = new Address(Buffer.from('cd2a3d9f938e13cd947ec05abc7fe734df8dd826', 'hex')) + const addr = new Address(hexStringToBytes('cd2a3d9f938e13cd947ec05abc7fe734df8dd826')) const acc = createAccount(BigInt(0), BigInt(0xff11)) t.test('should fail to get non-existent account', async (st) => { @@ -65,7 +65,7 @@ tape('cache put and get account', (t) => { }) t.test('should not have flushed to trie', async (st) => { - const res = await trie.get(addr.buf) + const res = await trie.get(addr.bytes) st.notOk(res) st.end() }) @@ -76,7 +76,7 @@ tape('cache put and get account', (t) => { }) t.test('trie should contain flushed account', async (st) => { - const raw = await trie.get(addr.buf) + const raw = await trie.get(addr.bytes) const res = Account.fromRlpSerializedAccount(raw!) st.equal(res.balance, acc.balance) st.end() @@ -95,7 +95,7 @@ tape('cache put and get account', (t) => { cache.put(addr, updatedAcc) await cache.flush() - const raw = await trie.get(addr.buf) + const raw = await trie.get(addr.bytes) const res = Account.fromRlpSerializedAccount(raw!) st.equal(res.balance, updatedAcc.balance) st.end() @@ -106,20 +106,20 @@ tape('cache checkpointing', (t) => { const trie = new Trie({ useKeyHashing: true }) const getCb: getCb = async (address) => { const innerTrie = trie - const rlp = await innerTrie.get(address.buf) + const rlp = await innerTrie.get(address.bytes) return rlp ? Account.fromRlpSerializedAccount(rlp) : undefined } const putCb: putCb = async (keyBuf, accountRlp) => { const innerTrie = trie await innerTrie.put(keyBuf, accountRlp) } - const deleteCb = async (keyBuf: Buffer) => { + const deleteCb = async (keyBuf: Uint8Array) => { const innerTrie = trie await innerTrie.del(keyBuf) } const cache = new Cache({ getCb, putCb, deleteCb }) - const addr = new Address(Buffer.from('cd2a3d9f938e13cd947ec05abc7fe734df8dd826', 'hex')) + const addr = new Address(hexStringToBytes('cd2a3d9f938e13cd947ec05abc7fe734df8dd826')) const acc = createAccount(BigInt(0), BigInt(0xff11)) const updatedAcc = createAccount(BigInt(0x00), BigInt(0xff00)) diff --git a/packages/statemanager/test/ethersStateManager.spec.ts b/packages/statemanager/test/ethersStateManager.spec.ts index c629f739ce..45ab64a462 100644 --- a/packages/statemanager/test/ethersStateManager.spec.ts +++ b/packages/statemanager/test/ethersStateManager.spec.ts @@ -1,7 +1,14 @@ import { Block } from '@ethereumjs/block' import { Chain, Common, Hardfork } from '@ethereumjs/common' import { FeeMarketEIP1559Transaction, TransactionFactory } from '@ethereumjs/tx' -import { Address, bigIntToBuffer, setLengthLeft } from '@ethereumjs/util' +import { + Address, + bigIntToBytes, + equalsBytes, + hexStringToBytes, + setLengthLeft, + utf8ToBytes, +} from '@ethereumjs/util' import { VM } from '@ethereumjs/vm' import { BaseProvider, JsonRpcProvider, StaticJsonRpcProvider } from '@ethersproject/providers' import * as tape from 'tape' @@ -77,20 +84,20 @@ tape('Ethers State Manager API tests', async (t) => { const storageSlot = await state.getContractStorage( UNIerc20ContractAddress, - setLengthLeft(bigIntToBuffer(1n), 32) + setLengthLeft(bigIntToBytes(1n), 32) ) t.ok(storageSlot.length > 0, 'was able to retrieve storage slot 1 for the UNI contract') await state.putContractStorage( UNIerc20ContractAddress, - setLengthLeft(bigIntToBuffer(2n), 32), - Buffer.from('abcd') + setLengthLeft(bigIntToBytes(2n), 32), + utf8ToBytes('abcd') ) const slotValue = await state.getContractStorage( UNIerc20ContractAddress, - setLengthLeft(bigIntToBuffer(2n), 32) + setLengthLeft(bigIntToBytes(2n), 32) ) - t.ok(slotValue.equals(Buffer.from('abcd')), 'should retrieve slot 2 value') + t.ok(equalsBytes(slotValue, utf8ToBytes('abcd')), 'should retrieve slot 2 value') // Verify that provider is not called for cached data ;(provider as any).getStorageAt = function () { @@ -99,14 +106,14 @@ tape('Ethers State Manager API tests', async (t) => { t.doesNotThrow( async () => - state.getContractStorage(UNIerc20ContractAddress, setLengthLeft(bigIntToBuffer(2n), 32)), + state.getContractStorage(UNIerc20ContractAddress, setLengthLeft(bigIntToBytes(2n), 32)), 'should not call provider.getStorageAt' ) await state.putContractStorage( UNIerc20ContractAddress, - setLengthLeft(bigIntToBuffer(2n), 32), - Buffer.from('') + setLengthLeft(bigIntToBytes(2n), 32), + new Uint8Array(0) ) // Verify that provider is not called @@ -126,7 +133,7 @@ tape('Ethers State Manager API tests', async (t) => { const deletedSlot = await state.getContractStorage( UNIerc20ContractAddress, - setLengthLeft(bigIntToBuffer(2n), 32) + setLengthLeft(bigIntToBytes(2n), 32) ) t.equal(deletedSlot.length, 0, 'deleted slot from storage cache') @@ -181,9 +188,8 @@ tape('runTx custom transaction test', async (t) => { const vm = await VM.create({ common, stateManager: state }) const vitalikDotEth = Address.fromString('0xd8da6bf26964af9d7eed9e03e53415d37aa96045') - const privateKey = Buffer.from( - 'e331b6d69882b4cb4ea581d88e0b604039a3de5967688d3dcffdd2270c0fd109', - 'hex' + const privateKey = hexStringToBytes( + 'e331b6d69882b4cb4ea581d88e0b604039a3de5967688d3dcffdd2270c0fd109' ) const tx = FeeMarketEIP1559Transaction.fromTxData( { to: vitalikDotEth, value: '0x100', gasLimit: 500000n, maxFeePerGas: 7 }, diff --git a/packages/statemanager/test/proofStateManager.spec.ts b/packages/statemanager/test/proofStateManager.spec.ts index caae1cbc11..51ddc44ba2 100644 --- a/packages/statemanager/test/proofStateManager.spec.ts +++ b/packages/statemanager/test/proofStateManager.spec.ts @@ -1,5 +1,5 @@ import { Trie } from '@ethereumjs/trie' -import { Address, toBuffer, zeros } from '@ethereumjs/util' +import { Address, bytesToHex, hexStringToBytes, zeros } from '@ethereumjs/util' import { keccak256 } from 'ethereum-cryptography/keccak' import * as tape from 'tape' @@ -13,8 +13,8 @@ tape('ProofStateManager', (t) => { t.test('should get and verify EIP 1178 proofs', async (st) => { const address = Address.zero() const key = zeros(32) - const value = Buffer.from('0000aabb00', 'hex') - const code = Buffer.from('6000', 'hex') + const value = hexStringToBytes('0000aabb00') + const code = hexStringToBytes('6000') const stateManager = new DefaultStateManager() await stateManager.checkpoint() await stateManager.putContractStorage(address, key, value) @@ -23,7 +23,7 @@ tape('ProofStateManager', (t) => { account.balance = BigInt(1) account.nonce = BigInt(2) await stateManager.putAccount(address, account) - const address2 = new Address(Buffer.from('20'.repeat(20), 'hex')) + const address2 = new Address(hexStringToBytes('20'.repeat(20))) const account2 = await stateManager.getAccount(address2) account.nonce = BigInt(2) await stateManager.putAccount(address2, account2) @@ -44,10 +44,10 @@ tape('ProofStateManager', (t) => { const trie = new Trie({ useKeyHashing: true }) const stateManager = new DefaultStateManager({ trie }) // Dump all the account proof data in the DB - let stateRoot: Buffer | undefined + let stateRoot: Uint8Array | undefined for (const proofData of ropsten_validAccount.accountProof) { - const bufferData = toBuffer(proofData) - const key = Buffer.from(keccak256(bufferData)) + const bufferData = hexStringToBytes(proofData) + const key = keccak256(bufferData) if (stateRoot === undefined) { stateRoot = key } @@ -72,10 +72,10 @@ tape('ProofStateManager', (t) => { const trie = new Trie({ useKeyHashing: true }) const stateManager = new DefaultStateManager({ trie }) // Dump all the account proof data in the DB - let stateRoot: Buffer | undefined + let stateRoot: Uint8Array | undefined for (const proofData of ropsten_nonexistentAccount.accountProof) { - const bufferData = toBuffer(proofData) - const key = Buffer.from(keccak256(bufferData)) + const bufferData = hexStringToBytes(proofData) + const key = keccak256(bufferData) if (stateRoot === undefined) { stateRoot = key } @@ -101,10 +101,10 @@ tape('ProofStateManager', (t) => { const trie = new Trie({ useKeyHashing: true }) const stateManager = new DefaultStateManager({ trie }) // Dump all the account proof data in the DB - let stateRoot: Buffer | undefined + let stateRoot: Uint8Array | undefined for (const proofData of ropsten_contractWithStorage.accountProof) { - const bufferData = toBuffer(proofData) - const key = Buffer.from(keccak256(bufferData)) + const bufferData = hexStringToBytes(proofData) + const key = keccak256(bufferData) if (stateRoot === undefined) { stateRoot = key } @@ -113,17 +113,17 @@ tape('ProofStateManager', (t) => { } const storageRoot = ropsten_contractWithStorage.storageHash const storageTrie = new Trie({ useKeyHashing: true }) - const storageKeys: Buffer[] = [] + const storageKeys: Uint8Array[] = [] for (const storageProofsData of ropsten_contractWithStorage.storageProof) { - storageKeys.push(toBuffer(storageProofsData.key)) + storageKeys.push(hexStringToBytes(storageProofsData.key)) for (const storageProofData of storageProofsData.proof) { - const key = Buffer.from(keccak256(toBuffer(storageProofData))) + const key = keccak256(hexStringToBytes(storageProofData)) // @ts-expect-error - await storageTrie._db.put(key, toBuffer(storageProofData)) + await storageTrie._db.put(key, hexStringToBytes(storageProofData)) } } - storageTrie.root(toBuffer(storageRoot)) - const addressHex = address.buf.toString('hex') + storageTrie.root(hexStringToBytes(storageRoot)) + const addressHex = bytesToHex(address.bytes) stateManager._storageTries[addressHex] = storageTrie trie.root(stateRoot!) @@ -143,10 +143,10 @@ tape('ProofStateManager', (t) => { const trie = new Trie({ useKeyHashing: true }) const stateManager = new DefaultStateManager({ trie }) // Dump all the account proof data in the DB - let stateRoot: Buffer | undefined + let stateRoot: Uint8Array | undefined for (const proofData of ropsten_contractWithStorage.accountProof) { - const bufferData = toBuffer(proofData) - const key = Buffer.from(keccak256(bufferData)) + const bufferData = hexStringToBytes(proofData) + const key = keccak256(bufferData) if (stateRoot === undefined) { stateRoot = key } @@ -155,17 +155,17 @@ tape('ProofStateManager', (t) => { } const storageRoot = ropsten_contractWithStorage.storageHash const storageTrie = new Trie({ useKeyHashing: true }) - const storageKeys: Buffer[] = [] + const storageKeys: Uint8Array[] = [] for (const storageProofsData of ropsten_contractWithStorage.storageProof) { - storageKeys.push(toBuffer(storageProofsData.key)) + storageKeys.push(hexStringToBytes(storageProofsData.key)) for (const storageProofData of storageProofsData.proof) { - const key = Buffer.from(keccak256(toBuffer(storageProofData))) + const key = keccak256(hexStringToBytes(storageProofData)) // @ts-expect-error - await storageTrie._db.put(key, toBuffer(storageProofData)) + await storageTrie._db.put(key, hexStringToBytes(storageProofData)) } } - storageTrie.root(toBuffer(storageRoot)) - const addressHex = address.buf.toString('hex') + storageTrie.root(hexStringToBytes(storageRoot)) + const addressHex = bytesToHex(address.bytes) stateManager._storageTries[addressHex] = storageTrie trie.root(stateRoot!) @@ -212,10 +212,10 @@ tape('ProofStateManager', (t) => { const trie = new Trie({ useKeyHashing: true }) const stateManager = new DefaultStateManager({ trie }) // Dump all the account proof data in the DB - let stateRoot: Buffer | undefined + let stateRoot: Uint8Array | undefined for (const proofData of ropsten_nonexistentAccount.accountProof) { - const bufferData = toBuffer(proofData) - const key = Buffer.from(keccak256(bufferData)) + const bufferData = hexStringToBytes(proofData) + const key = keccak256(bufferData) if (stateRoot === undefined) { stateRoot = key } @@ -224,8 +224,8 @@ tape('ProofStateManager', (t) => { } const storageRoot = ropsten_nonexistentAccount.storageHash const storageTrie = new Trie({ useKeyHashing: true }) - storageTrie.root(toBuffer(storageRoot)) - const addressHex = address.buf.toString('hex') + storageTrie.root(hexStringToBytes(storageRoot)) + const addressHex = bytesToHex(address.bytes) stateManager._storageTries[addressHex] = storageTrie trie.root(stateRoot!) diff --git a/packages/statemanager/test/stateManager.spec.ts b/packages/statemanager/test/stateManager.spec.ts index bc9c1004ee..23480495dd 100644 --- a/packages/statemanager/test/stateManager.spec.ts +++ b/packages/statemanager/test/stateManager.spec.ts @@ -3,12 +3,12 @@ import { Address, KECCAK256_RLP, KECCAK256_RLP_S, - toBuffer, - unpadBuffer, + hexStringToBytes, + unpadBytes, zeros, } from '@ethereumjs/util' import { keccak256 } from 'ethereum-cryptography/keccak' -import { bytesToHex } from 'ethereum-cryptography/utils' +import { bytesToHex, concatBytes, equalsBytes, hexToBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' // explicitly import `inherits` to fix karma-typescript issue // eslint-disable-next-line @typescript-eslint/no-unused-vars @@ -30,29 +30,29 @@ tape('StateManager', (t) => { t.test('should set the state root to empty', async (st) => { const stateManager = new DefaultStateManager() - st.ok(stateManager._trie.root().equals(KECCAK256_RLP), 'it has default root') + st.ok(equalsBytes(stateManager._trie.root(), KECCAK256_RLP), 'it has default root') // commit some data to the trie - const address = new Address(Buffer.from('a94f5374fce5edbc8e2a8697c15331677e6ebf0b', 'hex')) + const address = new Address(hexStringToBytes('a94f5374fce5edbc8e2a8697c15331677e6ebf0b')) const account = createAccount(BigInt(0), BigInt(1000)) await stateManager.checkpoint() await stateManager.putAccount(address, account) await stateManager.commit() await stateManager.flush() - st.ok(!stateManager._trie.root().equals(KECCAK256_RLP), 'it has a new root') + st.ok(!equalsBytes(stateManager._trie.root(), KECCAK256_RLP), 'it has a new root') // set state root to empty trie root - const emptyTrieRoot = Buffer.from(KECCAK256_RLP_S, 'hex') + const emptyTrieRoot = hexToBytes(KECCAK256_RLP_S) await stateManager.setStateRoot(emptyTrieRoot) const res = await stateManager.getStateRoot() - st.ok(res.equals(KECCAK256_RLP), 'it has default root') + st.ok(equalsBytes(res, KECCAK256_RLP), 'it has default root') st.end() }) t.test('should clear the cache when the state root is set', async (st) => { const stateManager = new DefaultStateManager() - const address = new Address(Buffer.from('a94f5374fce5edbc8e2a8697c15331677e6ebf0b', 'hex')) + const address = new Address(hexStringToBytes('a94f5374fce5edbc8e2a8697c15331677e6ebf0b')) const account = createAccount() // test account storage cache @@ -73,12 +73,14 @@ tape('StateManager', (t) => { // test contract storage cache await stateManager.checkpoint() - const key = toBuffer('0x1234567890123456789012345678901234567890123456789012345678901234') - const value = Buffer.from('0x1234') + const key = hexStringToBytes( + '0x1234567890123456789012345678901234567890123456789012345678901234' + ) + const value = hexStringToBytes('0x1234') await stateManager.putContractStorage(address, key, value) const contract0 = await stateManager.getContractStorage(address, key) - st.ok(contract0.equals(value), "contract key's value is set in the _storageTries cache") + st.ok(equalsBytes(contract0, value), "contract key's value is set in the _storageTries cache") await stateManager.commit() await stateManager.setStateRoot(initialStateRoot) @@ -93,7 +95,7 @@ tape('StateManager', (t) => { async (st) => { const stateManager = new DefaultStateManager() const account = createAccount() - const address = new Address(Buffer.from('a94f5374fce5edbc8e2a8697c15331677e6ebf0b', 'hex')) + const address = new Address(hexStringToBytes('a94f5374fce5edbc8e2a8697c15331677e6ebf0b')) await stateManager.putAccount(address, account) @@ -106,8 +108,8 @@ tape('StateManager', (t) => { const res2 = await stateManager.getAccount(address) - st.equal(stateManager._cache._cache.begin().pointer[0], address.buf.toString('hex')) - st.ok(res1.serialize().equals(res2.serialize())) + st.equal(stateManager._cache._cache.begin().pointer[0], bytesToHex(address.bytes)) + st.ok(equalsBytes(res1.serialize(), res2.serialize())) st.end() } @@ -117,7 +119,7 @@ tape('StateManager', (t) => { 'should call the callback with a boolean representing emptiness, when the account is empty', async (st) => { const stateManager = new DefaultStateManager() - const address = new Address(Buffer.from('a94f5374fce5edbc8e2a8697c15331677e6ebf0b', 'hex')) + const address = new Address(hexStringToBytes('a94f5374fce5edbc8e2a8697c15331677e6ebf0b')) const res = await stateManager.accountIsEmpty(address) @@ -129,7 +131,7 @@ tape('StateManager', (t) => { t.test('should return false for a non-existent account', async (st) => { const stateManager = new DefaultStateManager() - const address = new Address(Buffer.from('a94f5374fce5edbc8e2a8697c15331677e6ebf0b', 'hex')) + const address = new Address(hexStringToBytes('a94f5374fce5edbc8e2a8697c15331677e6ebf0b')) const res = await stateManager.accountExists(address) @@ -141,7 +143,7 @@ tape('StateManager', (t) => { t.test('should return true for an existent account', async (st) => { const stateManager = new DefaultStateManager() const account = createAccount(BigInt(0x1), BigInt(0x1)) - const address = new Address(Buffer.from('a94f5374fce5edbc8e2a8697c15331677e6ebf0b', 'hex')) + const address = new Address(hexStringToBytes('a94f5374fce5edbc8e2a8697c15331677e6ebf0b')) await stateManager.putAccount(address, account) @@ -157,7 +159,7 @@ tape('StateManager', (t) => { async (st) => { const stateManager = new DefaultStateManager() const account = createAccount(BigInt(0x1), BigInt(0x1)) - const address = new Address(Buffer.from('a94f5374fce5edbc8e2a8697c15331677e6ebf0b', 'hex')) + const address = new Address(hexStringToBytes('a94f5374fce5edbc8e2a8697c15331677e6ebf0b')) await stateManager.putAccount(address, account) @@ -172,7 +174,7 @@ tape('StateManager', (t) => { t.test('should modify account fields correctly', async (st) => { const stateManager = new DefaultStateManager() const account = createAccount() - const address = new Address(Buffer.from('a94f5374fce5edbc8e2a8697c15331677e6ebf0b', 'hex')) + const address = new Address(hexStringToBytes('a94f5374fce5edbc8e2a8697c15331677e6ebf0b')) await stateManager.putAccount(address, account) await stateManager.modifyAccountFields(address, { balance: BigInt(1234) }) @@ -188,24 +190,22 @@ tape('StateManager', (t) => { st.equal(res2.nonce, BigInt(1)) await stateManager.modifyAccountFields(address, { - codeHash: Buffer.from( - 'd748bf26ab37599c944babfdbeecf6690801bd61bf2670efb0a34adfc6dca10b', - 'hex' + codeHash: hexStringToBytes( + 'd748bf26ab37599c944babfdbeecf6690801bd61bf2670efb0a34adfc6dca10b' ), - storageRoot: Buffer.from( - 'cafd881ab193703b83816c49ff6c2bf6ba6f464a1be560c42106128c8dbc35e7', - 'hex' + storageRoot: hexStringToBytes( + 'cafd881ab193703b83816c49ff6c2bf6ba6f464a1be560c42106128c8dbc35e7' ), }) const res3 = await stateManager.getAccount(address) st.equal( - res3.codeHash.toString('hex'), + bytesToHex(res3.codeHash), 'd748bf26ab37599c944babfdbeecf6690801bd61bf2670efb0a34adfc6dca10b' ) st.equal( - res3.storageRoot.toString('hex'), + bytesToHex(res3.storageRoot), 'cafd881ab193703b83816c49ff6c2bf6ba6f464a1be560c42106128c8dbc35e7' ) @@ -216,7 +216,7 @@ tape('StateManager', (t) => { 'should modify account fields correctly on previously non-existent account', async (st) => { const stateManager = new DefaultStateManager() - const address = new Address(Buffer.from('a94f5374fce5edbc8e2a8697c15331677e6ebf0b', 'hex')) + const address = new Address(hexStringToBytes('a94f5374fce5edbc8e2a8697c15331677e6ebf0b')) await stateManager.modifyAccountFields(address, { balance: BigInt(1234) }) const res1 = await stateManager.getAccount(address) @@ -226,13 +226,11 @@ tape('StateManager', (t) => { const res2 = await stateManager.getAccount(address) st.equal(res2.nonce, BigInt(1)) - const newCodeHash = Buffer.from( - 'd748bf26ab37599c944babfdbeecf6690801bd61bf2670efb0a34adfc6dca10b', - 'hex' + const newCodeHash = hexStringToBytes( + 'd748bf26ab37599c944babfdbeecf6690801bd61bf2670efb0a34adfc6dca10b' ) - const newStorageRoot = Buffer.from( - 'cafd881ab193703b83816c49ff6c2bf6ba6f464a1be560c42106128c8dbc35e7', - 'hex' + const newStorageRoot = hexStringToBytes( + 'cafd881ab193703b83816c49ff6c2bf6ba6f464a1be560c42106128c8dbc35e7' ) await stateManager.modifyAccountFields(address, { codeHash: newCodeHash, @@ -240,21 +238,23 @@ tape('StateManager', (t) => { }) const res3 = await stateManager.getAccount(address) - st.ok(res3.codeHash.equals(newCodeHash)) - st.ok(res3.storageRoot.equals(newStorageRoot)) + st.ok(equalsBytes(res3.codeHash, newCodeHash)) + st.ok(equalsBytes(res3.storageRoot, newStorageRoot)) st.end() } ) t.test('should dump storage', async (st) => { const stateManager = new DefaultStateManager() - const address = new Address(Buffer.from('a94f5374fce5edbc8e2a8697c15331677e6ebf0b', 'hex')) + const address = new Address(hexStringToBytes('a94f5374fce5edbc8e2a8697c15331677e6ebf0b')) const account = createAccount() await stateManager.putAccount(address, account) - const key = toBuffer('0x1234567890123456789012345678901234567890123456789012345678901234') - const value = toBuffer('0x0a') // We used this value as its RLP encoding is also 0a + const key = hexStringToBytes( + '0x1234567890123456789012345678901234567890123456789012345678901234' + ) + const value = hexStringToBytes('0x0a') // We used this value as its RLP encoding is also 0a await stateManager.putContractStorage(address, key, value) const data = await stateManager.dumpStorage(address) @@ -266,9 +266,9 @@ tape('StateManager', (t) => { t.test("should validate the key's length when modifying a contract's storage", async (st) => { const stateManager = new DefaultStateManager() - const address = new Address(Buffer.from('a94f5374fce5edbc8e2a8697c15331677e6ebf0b', 'hex')) + const address = new Address(hexStringToBytes('a94f5374fce5edbc8e2a8697c15331677e6ebf0b')) try { - await stateManager.putContractStorage(address, Buffer.alloc(12), toBuffer('0x1231')) + await stateManager.putContractStorage(address, new Uint8Array(12), hexStringToBytes('0x1231')) } catch (e: any) { st.equal(e.message, 'Storage key must be 32 bytes long') st.end() @@ -281,9 +281,9 @@ tape('StateManager', (t) => { t.test("should validate the key's length when reading a contract's storage", async (st) => { const stateManager = new DefaultStateManager() - const address = new Address(Buffer.from('a94f5374fce5edbc8e2a8697c15331677e6ebf0b', 'hex')) + const address = new Address(hexStringToBytes('a94f5374fce5edbc8e2a8697c15331677e6ebf0b')) try { - await stateManager.getContractStorage(address, Buffer.alloc(12)) + await stateManager.getContractStorage(address, new Uint8Array(12)) } catch (e: any) { st.equal(e.message, 'Storage key must be 32 bytes long') st.end() @@ -308,9 +308,9 @@ tape('StateManager', (t) => { // Setup const stateManager = new DefaultStateManager() const codeStateManager = new DefaultStateManager() - const address1 = new Address(Buffer.from('a94f5374fce5edbc8e2a8697c15331677e6ebf0b', 'hex')) - const key1 = Buffer.from('00'.repeat(32), 'hex') - const key2 = Buffer.from('00'.repeat(31) + '01', 'hex') + const address1 = new Address(hexStringToBytes('a94f5374fce5edbc8e2a8697c15331677e6ebf0b')) + const key1 = hexStringToBytes('00'.repeat(32)) + const key2 = hexStringToBytes('00'.repeat(31) + '01') await stateManager.putContractStorage(address1, key1, key2) await stateManager.putContractStorage(address1, key2, key2) @@ -367,10 +367,9 @@ tape('StateManager - Contract code', (tester) => { const it = tester.test it('should set and get code', async (t) => { const stateManager = new DefaultStateManager() - const address = new Address(Buffer.from('a94f5374fce5edbc8e2a8697c15331677e6ebf0b', 'hex')) - const code = Buffer.from( - '73095e7baea6a6c7c4c2dfeb977efac326af552d873173095e7baea6a6c7c4c2dfeb977efac326af552d873157', - 'hex' + const address = new Address(hexStringToBytes('a94f5374fce5edbc8e2a8697c15331677e6ebf0b')) + const code = hexStringToBytes( + '73095e7baea6a6c7c4c2dfeb977efac326af552d873173095e7baea6a6c7c4c2dfeb977efac326af552d873157' ) const raw = { nonce: '0x0', @@ -382,13 +381,13 @@ tape('StateManager - Contract code', (tester) => { await stateManager.putAccount(address, account) await stateManager.putContractCode(address, code) const codeRetrieved = await stateManager.getContractCode(address) - t.ok(code.equals(codeRetrieved)) + t.ok(equalsBytes(code, codeRetrieved)) t.end() }) it('should not get code if is not contract', async (t) => { const stateManager = new DefaultStateManager() - const address = new Address(Buffer.from('a94f5374fce5edbc8e2a8697c15331677e6ebf0b', 'hex')) + const address = new Address(hexStringToBytes('a94f5374fce5edbc8e2a8697c15331677e6ebf0b')) const raw = { nonce: '0x0', balance: '0x03e7', @@ -396,33 +395,33 @@ tape('StateManager - Contract code', (tester) => { const account = Account.fromAccountData(raw) await stateManager.putAccount(address, account) const code = await stateManager.getContractCode(address) - t.ok(code.equals(Buffer.alloc(0))) + t.ok(equalsBytes(code, new Uint8Array(0))) t.end() }) it('should set empty code', async (t) => { const stateManager = new DefaultStateManager() - const address = new Address(Buffer.from('a94f5374fce5edbc8e2a8697c15331677e6ebf0b', 'hex')) + const address = new Address(hexStringToBytes('a94f5374fce5edbc8e2a8697c15331677e6ebf0b')) const raw = { nonce: '0x0', balance: '0x03e7', } const account = Account.fromAccountData(raw) - const code = Buffer.alloc(0) + const code = new Uint8Array(0) await stateManager.putAccount(address, account) await stateManager.putContractCode(address, code) const codeRetrieved = await stateManager.getContractCode(address) - t.ok(codeRetrieved.equals(Buffer.alloc(0))) + t.ok(equalsBytes(codeRetrieved, new Uint8Array(0))) t.end() }) it('should prefix codehashes by default', async (t) => { const stateManager = new DefaultStateManager() - const address = new Address(Buffer.from('a94f5374fce5edbc8e2a8697c15331677e6ebf0b', 'hex')) - const code = Buffer.from('80', 'hex') + const address = new Address(hexStringToBytes('a94f5374fce5edbc8e2a8697c15331677e6ebf0b')) + const code = hexStringToBytes('80') await stateManager.putContractCode(address, code) const codeRetrieved = await stateManager.getContractCode(address) - t.ok(codeRetrieved.equals(code)) + t.ok(equalsBytes(codeRetrieved, code)) t.end() }) @@ -430,8 +429,8 @@ tape('StateManager - Contract code', (tester) => { const stateManager = new DefaultStateManager({ prefixCodeHashes: false, }) - const address = new Address(Buffer.from('a94f5374fce5edbc8e2a8697c15331677e6ebf0b', 'hex')) - const code = Buffer.from('80', 'hex') + const address = new Address(hexStringToBytes('a94f5374fce5edbc8e2a8697c15331677e6ebf0b')) + const code = hexStringToBytes('80') try { await stateManager.putContractCode(address, code) t.fail('should throw') @@ -450,7 +449,7 @@ tape('StateManager - Contract storage', (tester) => { const stateManager = new DefaultStateManager() const address = Address.zero() const key = zeros(32) - const value = Buffer.from('aa'.repeat(33), 'hex') + const value = hexStringToBytes('aa'.repeat(33)) try { await stateManager.putContractStorage(address, key, value) t.fail('did not throw') @@ -465,26 +464,26 @@ tape('StateManager - Contract storage', (tester) => { const address = Address.zero() const key0 = zeros(32) - const value0 = Buffer.from('00' + 'aa'.repeat(30), 'hex') // put a value of 31-bytes length with a leading zero byte - const expect0 = unpadBuffer(value0) + const value0 = hexStringToBytes('00' + 'aa'.repeat(30)) // put a value of 31-bytes length with a leading zero byte + const expect0 = unpadBytes(value0) await stateManager.putContractStorage(address, key0, value0) const slot0 = await stateManager.getContractStorage(address, key0) - t.ok(slot0.equals(expect0), 'value of 31 bytes padded correctly') + t.ok(equalsBytes(slot0, expect0), 'value of 31 bytes padded correctly') - const key1 = Buffer.concat([zeros(31), Buffer.from('01', 'hex')]) - const value1 = Buffer.from('0000' + 'aa'.repeat(1), 'hex') // put a value of 1-byte length with two leading zero bytes - const expect1 = unpadBuffer(value1) + const key1 = concatBytes(zeros(31), hexStringToBytes('01')) + const value1 = hexStringToBytes('0000' + 'aa'.repeat(1)) // put a value of 1-byte length with two leading zero bytes + const expect1 = unpadBytes(value1) await stateManager.putContractStorage(address, key1, value1) const slot1 = await stateManager.getContractStorage(address, key1) - t.ok(slot1.equals(expect1), 'value of 1 byte padded correctly') + t.ok(equalsBytes(slot1, expect1), 'value of 1 byte padded correctly') t.end() }) it('should delete storage values which only consist of zero bytes', async (t) => { const address = Address.zero() const key = zeros(32) - const startValue = Buffer.from('01', 'hex') + const startValue = hexStringToBytes('01') const zeroLengths = [0, 1, 31, 32] // checks for arbitrary-length zeros t.plan(zeroLengths.length) @@ -494,14 +493,14 @@ tape('StateManager - Contract storage', (tester) => { const value = zeros(length) await stateManager.putContractStorage(address, key, startValue) const currentValue = await stateManager.getContractStorage(address, key) - if (!currentValue.equals(startValue)) { + if (!equalsBytes(currentValue, startValue)) { // sanity check t.fail('contract value not set correctly') } else { // delete the value await stateManager.putContractStorage(address, key, value) const deleted = await stateManager.getContractStorage(address, key) - t.ok(deleted.equals(zeros(0)), 'the storage key should be deleted') + t.ok(equalsBytes(deleted, zeros(0)), 'the storage key should be deleted') } } t.end() @@ -510,12 +509,12 @@ tape('StateManager - Contract storage', (tester) => { it('should not strip trailing zeros', async (t) => { const address = Address.zero() const key = zeros(32) - const value = Buffer.from('0000aabb00', 'hex') - const expect = Buffer.from('aabb00', 'hex') + const value = hexToBytes('0000aabb00') + const expect = hexToBytes('aabb00') const stateManager = new DefaultStateManager() await stateManager.putContractStorage(address, key, value) const contractValue = await stateManager.getContractStorage(address, key) - t.ok(contractValue.equals(expect), 'trailing zeros are not stripped') + t.ok(equalsBytes(contractValue, expect), 'trailing zeros are not stripped') t.end() }) }) diff --git a/packages/trie/benchmarks/engines/level.ts b/packages/trie/benchmarks/engines/level.ts index 73623019d6..e172c9adfe 100644 --- a/packages/trie/benchmarks/engines/level.ts +++ b/packages/trie/benchmarks/engines/level.ts @@ -4,14 +4,14 @@ import { MemoryLevel } from 'memory-level' import type { BatchDBOp, DB } from '../../src/types' import type { AbstractLevel } from 'abstract-level' -export const ENCODING_OPTS = { keyEncoding: 'buffer', valueEncoding: 'buffer' } +export const ENCODING_OPTS = { keyEncoding: 'Uint8Array', valueEncoding: 'Uint8Array' } /** * LevelDB is a thin wrapper around the underlying levelup db, * which validates inputs and sets encoding type. */ export class LevelDB implements DB { - _leveldb: AbstractLevel + _leveldb: AbstractLevel /** * Initialize a DB instance. If `leveldb` is not provided, DB @@ -19,7 +19,7 @@ export class LevelDB implements DB { * @param leveldb - An abstract-leveldown compliant store */ constructor( - leveldb?: AbstractLevel | null + leveldb?: AbstractLevel | null ) { this._leveldb = leveldb ?? new MemoryLevel(ENCODING_OPTS) } @@ -27,8 +27,8 @@ export class LevelDB implements DB { /** * @inheritDoc */ - async get(key: Buffer): Promise { - let value: Buffer | null = null + async get(key: Uint8Array): Promise { + let value: Uint8Array | null = null try { value = await this._leveldb.get(key, ENCODING_OPTS) } catch (error: any) { @@ -45,14 +45,14 @@ export class LevelDB implements DB { /** * @inheritDoc */ - async put(key: Buffer, val: Buffer): Promise { + async put(key: Uint8Array, val: Uint8Array): Promise { await this._leveldb.put(key, val, ENCODING_OPTS) } /** * @inheritDoc */ - async del(key: Buffer): Promise { + async del(key: Uint8Array): Promise { await this._leveldb.del(key, ENCODING_OPTS) } diff --git a/packages/trie/benchmarks/keys.ts b/packages/trie/benchmarks/keys.ts index 86d7451a38..15e0ff52e5 100644 --- a/packages/trie/benchmarks/keys.ts +++ b/packages/trie/benchmarks/keys.ts @@ -2,8 +2,8 @@ import { keccak256 } from 'ethereum-cryptography/keccak' let curr = keccak256(new Uint8Array(32)) -export const keys: Buffer[] = [] +export const keys: Uint8Array[] = [] for (let i = 0; i < 5000; curr = keccak256(curr), i++) { - keys.push(Buffer.from(curr)) + keys.push(curr) } diff --git a/packages/trie/benchmarks/suite.ts b/packages/trie/benchmarks/suite.ts index 2704feb525..6bd60c4af5 100644 --- a/packages/trie/benchmarks/suite.ts +++ b/packages/trie/benchmarks/suite.ts @@ -27,15 +27,15 @@ export function createSuite(db: DB) { ['1k-1k-32-mir', 1000, true], ]) { await mark(title, async () => { - let key = Buffer.alloc(KEY_SIZE) + let key = new Uint8Array(KEY_SIZE) for (let i = 0; i <= ROUNDS; i++) { - key = Buffer.from(keccak256(key)) + key = keccak256(key) if (symmetric) { await trie.put(key, key) } else { - await trie.put(key, Buffer.from(key)) + await trie.put(key, key) } if (i % (eraSize as number) === 0) { diff --git a/packages/trie/examples/level.js b/packages/trie/examples/level.js index 97c4619e92..e6789a084d 100644 --- a/packages/trie/examples/level.js +++ b/packages/trie/examples/level.js @@ -3,7 +3,7 @@ const { MemoryLevel } = require('memory-level') const { Trie } = require('../dist') -const ENCODING_OPTS = { keyEncoding: 'buffer', valueEncoding: 'buffer' } +const ENCODING_OPTS = { keyEncoding: 'view', valueEncoding: 'view' } class LevelDB { _leveldb diff --git a/packages/trie/recipes/level-legacy.ts b/packages/trie/recipes/level-legacy.ts index c06c008e0a..0040f87269 100644 --- a/packages/trie/recipes/level-legacy.ts +++ b/packages/trie/recipes/level-legacy.ts @@ -12,8 +12,8 @@ export class LevelDB implements DB { this._leveldb = leveldb ?? level() } - async get(key: Buffer): Promise { - let value: Buffer | null = null + async get(key: Uint8Array): Promise { + let value: Uint8Array | null = null try { value = await this._leveldb.get(key, ENCODING_OPTS) } catch (error: any) { @@ -27,11 +27,11 @@ export class LevelDB implements DB { return value } - async put(key: Buffer, val: Buffer): Promise { + async put(key: Uint8Array, val: Uint8Array): Promise { await this._leveldb.put(key, val, ENCODING_OPTS) } - async del(key: Buffer): Promise { + async del(key: Uint8Array): Promise { await this._leveldb.del(key, ENCODING_OPTS) } diff --git a/packages/trie/recipes/level.ts b/packages/trie/recipes/level.ts index 62ac888cdb..6a7744a441 100644 --- a/packages/trie/recipes/level.ts +++ b/packages/trie/recipes/level.ts @@ -6,16 +6,24 @@ import type { AbstractLevel } from 'abstract-level' const ENCODING_OPTS = { keyEncoding: 'buffer', valueEncoding: 'buffer' } export class LevelDB implements DB { - readonly _leveldb: AbstractLevel + readonly _leveldb: AbstractLevel< + string | Uint8Array | Uint8Array, + string | Uint8Array, + string | Uint8Array + > constructor( - leveldb?: AbstractLevel | null + leveldb?: AbstractLevel< + string | Uint8Array | Uint8Array, + string | Uint8Array, + string | Uint8Array + > | null ) { this._leveldb = leveldb ?? new MemoryLevel(ENCODING_OPTS) } - async get(key: Buffer): Promise { - let value: Buffer | null = null + async get(key: Uint8Array): Promise { + let value: Uint8Array | null = null try { value = await this._leveldb.get(key, ENCODING_OPTS) } catch (error: any) { @@ -29,11 +37,11 @@ export class LevelDB implements DB { return value } - async put(key: Buffer, val: Buffer): Promise { + async put(key: Uint8Array, val: Uint8Array): Promise { await this._leveldb.put(key, val, ENCODING_OPTS) } - async del(key: Buffer): Promise { + async del(key: Uint8Array): Promise { await this._leveldb.del(key, ENCODING_OPTS) } diff --git a/packages/trie/recipes/lmdb.ts b/packages/trie/recipes/lmdb.ts index 91fc693b51..07d2ba4290 100644 --- a/packages/trie/recipes/lmdb.ts +++ b/packages/trie/recipes/lmdb.ts @@ -15,15 +15,15 @@ export class LMDB implements DB { }) } - async get(key: Buffer): Promise { + async get(key: Uint8Array): Promise { return this._database.get(key) } - async put(key: Buffer, val: Buffer): Promise { + async put(key: Uint8Array, val: Uint8Array): Promise { await this._database.put(key, val) } - async del(key: Buffer): Promise { + async del(key: Uint8Array): Promise { await this._database.remove(key) } diff --git a/packages/trie/src/db/checkpoint.ts b/packages/trie/src/db/checkpoint.ts index 4a7a0b2218..26c13e101f 100644 --- a/packages/trie/src/db/checkpoint.ts +++ b/packages/trie/src/db/checkpoint.ts @@ -1,3 +1,5 @@ +import { bytesToHex, hexStringToBytes } from '@ethereumjs/util' + import type { BatchDBOp, Checkpoint, DB } from '../types' /** @@ -43,8 +45,8 @@ export class CheckpointDB implements DB { * Adds a new checkpoint to the stack * @param root */ - checkpoint(root: Buffer) { - this.checkpoints.push({ keyValueMap: new Map(), root }) + checkpoint(root: Uint8Array) { + this.checkpoints.push({ keyValueMap: new Map(), root }) } /** @@ -59,12 +61,12 @@ export class CheckpointDB implements DB { if (value === null) { batchOp.push({ type: 'del', - key: Buffer.from(key, 'binary'), + key: hexStringToBytes(key), }) } else { batchOp.push({ type: 'put', - key: Buffer.from(key, 'binary'), + key: hexStringToBytes(key), value, }) } @@ -90,10 +92,10 @@ export class CheckpointDB implements DB { /** * @inheritDoc */ - async get(key: Buffer): Promise { + async get(key: Uint8Array): Promise { // Lookup the value in our cache. We return the latest checkpointed value (which should be the value on disk) for (let index = this.checkpoints.length - 1; index >= 0; index--) { - const value = this.checkpoints[index].keyValueMap.get(key.toString('binary')) + const value = this.checkpoints[index].keyValueMap.get(bytesToHex(key)) if (value !== undefined) { return value } @@ -103,7 +105,7 @@ export class CheckpointDB implements DB { const value = await this.db.get(key) if (this.hasCheckpoints()) { // Since we are a checkpoint, put this value in cache, so future `get` calls will not look the key up again from disk. - this.checkpoints[this.checkpoints.length - 1].keyValueMap.set(key.toString('binary'), value) + this.checkpoints[this.checkpoints.length - 1].keyValueMap.set(bytesToHex(key), value) } return value @@ -112,10 +114,10 @@ export class CheckpointDB implements DB { /** * @inheritDoc */ - async put(key: Buffer, val: Buffer): Promise { + async put(key: Uint8Array, val: Uint8Array): Promise { if (this.hasCheckpoints()) { // put value in cache - this.checkpoints[this.checkpoints.length - 1].keyValueMap.set(key.toString('binary'), val) + this.checkpoints[this.checkpoints.length - 1].keyValueMap.set(bytesToHex(key), val) } else { await this.db.put(key, val) } @@ -124,10 +126,10 @@ export class CheckpointDB implements DB { /** * @inheritDoc */ - async del(key: Buffer): Promise { + async del(key: Uint8Array): Promise { if (this.hasCheckpoints()) { // delete the value in the current cache - this.checkpoints[this.checkpoints.length - 1].keyValueMap.set(key.toString('binary'), null) + this.checkpoints[this.checkpoints.length - 1].keyValueMap.set(bytesToHex(key), null) } else { // delete the value on disk await this.db.del(key) diff --git a/packages/trie/src/db/map.ts b/packages/trie/src/db/map.ts index c272264320..1a45b2879b 100644 --- a/packages/trie/src/db/map.ts +++ b/packages/trie/src/db/map.ts @@ -1,14 +1,16 @@ +import { bytesToHex } from 'ethereum-cryptography/utils' + import type { BatchDBOp, DB } from '../types' export class MapDB implements DB { - _database: Map + _database: Map - constructor(database?: Map) { + constructor(database?: Map) { this._database = database ?? new Map() } - async get(key: Buffer): Promise { - const result = this._database.get(key.toString('hex')) + async get(key: Uint8Array): Promise { + const result = this._database.get(bytesToHex(key)) if (result !== undefined) { return result @@ -17,12 +19,12 @@ export class MapDB implements DB { return null } - async put(key: Buffer, val: Buffer): Promise { - this._database.set(key.toString('hex'), val) + async put(key: Uint8Array, val: Uint8Array): Promise { + this._database.set(bytesToHex(key), val) } - async del(key: Buffer): Promise { - this._database.delete(key.toString('hex')) + async del(key: Uint8Array): Promise { + this._database.delete(bytesToHex(key)) } async batch(opStack: BatchDBOp[]): Promise { diff --git a/packages/trie/src/proof/range.ts b/packages/trie/src/proof/range.ts index 8e734e49d7..9e370a07f2 100644 --- a/packages/trie/src/proof/range.ts +++ b/packages/trie/src/proof/range.ts @@ -1,5 +1,7 @@ +import { equalsBytes } from 'ethereum-cryptography/utils' + import { BranchNode, ExtensionNode, LeafNode, Trie } from '../trie' -import { nibblesCompare, nibblesToBuffer } from '../util/nibbles' +import { nibblesCompare, nibblestoBytes } from '../util/nibbles' import type { HashKeysFunction, Nibbles, TrieNode } from '../types' @@ -160,8 +162,8 @@ async function unsetInternal(trie: Trie, left: Nibbles, right: Nibbles): Promise } // Stop searching if `left` and `right` are not equal - if (!(leftNode instanceof Buffer)) { - if (rightNode instanceof Buffer) { + if (!(leftNode instanceof Uint8Array)) { + if (rightNode instanceof Uint8Array) { break } @@ -171,7 +173,7 @@ async function unsetInternal(trie: Trie, left: Nibbles, right: Nibbles): Promise let abort = false for (let i = 0; i < leftNode.length; i++) { - if (leftNode[i].compare(rightNode[i]) !== 0) { + if (!equalsBytes(leftNode[i], rightNode[i])) { abort = true break } @@ -180,11 +182,11 @@ async function unsetInternal(trie: Trie, left: Nibbles, right: Nibbles): Promise break } } else { - if (!(rightNode instanceof Buffer)) { + if (!(rightNode instanceof Uint8Array)) { break } - if (leftNode.compare(rightNode) !== 0) { + if (!equalsBytes(leftNode, rightNode)) { break } } @@ -314,11 +316,11 @@ async function unsetInternal(trie: Trie, left: Nibbles, right: Nibbles): Promise * @returns The value from the key, or null if valid proof of non-existence. */ async function verifyProof( - rootHash: Buffer, - key: Buffer, - proof: Buffer[], + rootHash: Uint8Array, + key: Uint8Array, + proof: Uint8Array[], useKeyHashingFunction: HashKeysFunction -): Promise<{ value: Buffer | null; trie: Trie }> { +): Promise<{ value: Uint8Array | null; trie: Trie }> { const proofTrie = new Trie({ root: rootHash, useKeyHashingFunction }) try { await proofTrie.fromProof(proof) @@ -408,12 +410,12 @@ async function hasRightElement(trie: Trie, key: Nibbles): Promise { * @returns a flag to indicate whether there exists more trie node in the trie */ export async function verifyRangeProof( - rootHash: Buffer, + rootHash: Uint8Array, firstKey: Nibbles | null, lastKey: Nibbles | null, keys: Nibbles[], - values: Buffer[], - proof: Buffer[] | null, + values: Uint8Array[], + proof: Uint8Array[] | null, useKeyHashingFunction: HashKeysFunction ): Promise { if (keys.length !== values.length) { @@ -437,9 +439,9 @@ export async function verifyRangeProof( if (proof === null && firstKey === null && lastKey === null) { const trie = new Trie({ useKeyHashingFunction }) for (let i = 0; i < keys.length; i++) { - await trie.put(nibblesToBuffer(keys[i]), values[i]) + await trie.put(nibblestoBytes(keys[i]), values[i]) } - if (rootHash.compare(trie.root()) !== 0) { + if (!equalsBytes(rootHash, trie.root())) { throw new Error('invalid all elements proof: root mismatch') } return false @@ -455,7 +457,7 @@ export async function verifyRangeProof( if (keys.length === 0) { const { trie, value } = await verifyProof( rootHash, - nibblesToBuffer(firstKey), + nibblestoBytes(firstKey), proof, useKeyHashingFunction ) @@ -471,7 +473,7 @@ export async function verifyRangeProof( if (keys.length === 1 && nibblesCompare(firstKey, lastKey) === 0) { const { trie, value } = await verifyProof( rootHash, - nibblesToBuffer(firstKey), + nibblestoBytes(firstKey), proof, useKeyHashingFunction ) @@ -479,7 +481,7 @@ export async function verifyRangeProof( if (nibblesCompare(firstKey, keys[0]) !== 0) { throw new Error('invalid one element proof: firstKey should be equal to keys[0]') } - if (value === null || value.compare(values[0]) !== 0) { + if (value === null || !equalsBytes(value, values[0])) { throw new Error('invalid one element proof: value mismatch') } @@ -507,11 +509,11 @@ export async function verifyRangeProof( // Put all elements to the trie for (let i = 0; i < keys.length; i++) { - await trie.put(nibblesToBuffer(keys[i]), values[i]) + await trie.put(nibblestoBytes(keys[i]), values[i]) } // Compare rootHash - if (trie.root().compare(rootHash) !== 0) { + if (!equalsBytes(trie.root(), rootHash)) { throw new Error('invalid two edge elements proof: root mismatch') } diff --git a/packages/trie/src/trie/node/branch.ts b/packages/trie/src/trie/node/branch.ts index c0b50679db..f9945d17e4 100644 --- a/packages/trie/src/trie/node/branch.ts +++ b/packages/trie/src/trie/node/branch.ts @@ -1,25 +1,24 @@ import { RLP } from '@ethereumjs/rlp' -import { bufArrToArr } from '@ethereumjs/util' import type { EmbeddedNode } from '../../types' export class BranchNode { _branches: (EmbeddedNode | null)[] - _value: Buffer | null + _value: Uint8Array | null constructor() { this._branches = new Array(16).fill(null) this._value = null } - static fromArray(arr: Buffer[]): BranchNode { + static fromArray(arr: Uint8Array[]): BranchNode { const node = new BranchNode() node._branches = arr.slice(0, 16) node._value = arr[16] return node } - value(v?: Buffer | null): Buffer | null { + value(v?: Uint8Array | null): Uint8Array | null { if (v !== null && v !== undefined) { this._value = v } @@ -35,8 +34,8 @@ export class BranchNode { return [...this._branches, this._value] } - serialize(): Buffer { - return Buffer.from(RLP.encode(bufArrToArr(this.raw() as Buffer[]))) + serialize(): Uint8Array { + return RLP.encode(this.raw() as Uint8Array[]) } getBranch(i: number) { diff --git a/packages/trie/src/trie/node/extension.ts b/packages/trie/src/trie/node/extension.ts index 75615868b3..8cfbaf1020 100644 --- a/packages/trie/src/trie/node/extension.ts +++ b/packages/trie/src/trie/node/extension.ts @@ -5,7 +5,7 @@ import { Node } from './node' import type { Nibbles } from '../../types' export class ExtensionNode extends Node { - constructor(nibbles: Nibbles, value: Buffer) { + constructor(nibbles: Nibbles, value: Uint8Array) { super(nibbles, value, false) } diff --git a/packages/trie/src/trie/node/leaf.ts b/packages/trie/src/trie/node/leaf.ts index 198c3ee4e2..64b3c53a4a 100644 --- a/packages/trie/src/trie/node/leaf.ts +++ b/packages/trie/src/trie/node/leaf.ts @@ -5,7 +5,7 @@ import { Node } from './node' import type { Nibbles } from '../../types' export class LeafNode extends Node { - constructor(nibbles: Nibbles, value: Buffer) { + constructor(nibbles: Nibbles, value: Uint8Array) { super(nibbles, value, true) } diff --git a/packages/trie/src/trie/node/node.ts b/packages/trie/src/trie/node/node.ts index a24623bcd6..e5b3ea5bcf 100644 --- a/packages/trie/src/trie/node/node.ts +++ b/packages/trie/src/trie/node/node.ts @@ -1,17 +1,16 @@ import { RLP } from '@ethereumjs/rlp' -import { bufArrToArr } from '@ethereumjs/util' import { addHexPrefix, removeHexPrefix } from '../../util/hex' -import { nibblesToBuffer } from '../../util/nibbles' +import { nibblestoBytes } from '../../util/nibbles' import type { Nibbles } from '../../types' export class Node { _nibbles: Nibbles - _value: Buffer + _value: Uint8Array _terminator: boolean - constructor(nibbles: Nibbles, value: Buffer, terminator: boolean) { + constructor(nibbles: Nibbles, value: Uint8Array, terminator: boolean) { this._nibbles = nibbles this._value = value this._terminator = terminator @@ -33,7 +32,7 @@ export class Node { return this._nibbles.length } - value(v?: Buffer) { + value(v?: Uint8Array) { if (v !== undefined) { this._value = v } @@ -45,11 +44,11 @@ export class Node { return addHexPrefix(this._nibbles.slice(0), this._terminator) } - raw(): [Buffer, Buffer] { - return [nibblesToBuffer(this.encodedKey()), this._value] + raw(): [Uint8Array, Uint8Array] { + return [nibblestoBytes(this.encodedKey()), this._value] } - serialize(): Buffer { - return Buffer.from(RLP.encode(bufArrToArr(this.raw()))) + serialize(): Uint8Array { + return RLP.encode(this.raw()) } } diff --git a/packages/trie/src/trie/node/util.ts b/packages/trie/src/trie/node/util.ts index 8a9ac0946d..10f471655d 100644 --- a/packages/trie/src/trie/node/util.ts +++ b/packages/trie/src/trie/node/util.ts @@ -1,18 +1,17 @@ import { RLP } from '@ethereumjs/rlp' -import { arrToBufArr } from '@ethereumjs/util' import { isTerminator } from '../../util/hex' -import { bufferToNibbles } from '../../util/nibbles' +import { bytesToNibbles } from '../../util/nibbles' import { BranchNode } from './branch' import { ExtensionNode } from './extension' import { LeafNode } from './leaf' -export function decodeRawNode(raw: Buffer[]) { +export function decodeRawNode(raw: Uint8Array[]) { if (raw.length === 17) { return BranchNode.fromArray(raw) } else if (raw.length === 2) { - const nibbles = bufferToNibbles(raw[0]) + const nibbles = bytesToNibbles(raw[0]) if (isTerminator(nibbles)) { return new LeafNode(LeafNode.decodeKey(nibbles), raw[1]) } @@ -22,8 +21,8 @@ export function decodeRawNode(raw: Buffer[]) { } } -export function decodeNode(raw: Buffer) { - const des = arrToBufArr(RLP.decode(Uint8Array.from(raw))) as Buffer[] +export function decodeNode(raw: Uint8Array) { + const des = RLP.decode(Uint8Array.from(raw)) as Uint8Array[] if (!Array.isArray(des)) { throw new Error('Invalid node') } @@ -31,5 +30,5 @@ export function decodeNode(raw: Buffer) { } export function isRawNode(n: any) { - return Array.isArray(n) && !Buffer.isBuffer(n) + return Array.isArray(n) && !(n instanceof Uint8Array) } diff --git a/packages/trie/src/trie/trie.ts b/packages/trie/src/trie/trie.ts index dd2bf0e949..dafa5b6159 100644 --- a/packages/trie/src/trie/trie.ts +++ b/packages/trie/src/trie/trie.ts @@ -1,11 +1,11 @@ -import { RLP_EMPTY_STRING } from '@ethereumjs/util' +import { RLP_EMPTY_STRING, bytesToHex, bytesToUtf8, equalsBytes } from '@ethereumjs/util' import { keccak256 } from 'ethereum-cryptography/keccak' import { CheckpointDB, MapDB } from '../db' import { verifyRangeProof } from '../proof/range' import { ROOT_DB_KEY } from '../types' import { Lock } from '../util/lock' -import { bufferToNibbles, doKeysMatch, matchingNibbleLength } from '../util/nibbles' +import { bytesToNibbles, doKeysMatch, matchingNibbleLength } from '../util/nibbles' import { TrieReadStream as ReadStream } from '../util/readStream' import { WalkController } from '../util/walkController' @@ -42,13 +42,13 @@ export class Trie { } /** The root for an empty trie */ - EMPTY_TRIE_ROOT: Buffer + EMPTY_TRIE_ROOT: Uint8Array /** The backend DB */ protected _db!: CheckpointDB protected _hashLen: number protected _lock = new Lock() - protected _root: Buffer + protected _root: Uint8Array /** * Creates a new trie. @@ -76,11 +76,9 @@ export class Trie { let key = ROOT_DB_KEY if (opts?.useKeyHashing === true) { - key = (opts?.useKeyHashingFunction ?? keccak256)(ROOT_DB_KEY) as Buffer + key = (opts?.useKeyHashingFunction ?? keccak256)(ROOT_DB_KEY) as Uint8Array } - key = Buffer.from(key) - if (opts?.db !== undefined && opts?.useRootPersistence === true) { if (opts?.root === undefined) { opts.root = (await opts?.db.get(key)) ?? undefined @@ -107,7 +105,7 @@ export class Trie { /** * Gets and/or Sets the current root of the `trie` */ - root(value?: Buffer | null): Buffer { + root(value?: Uint8Array | null): Uint8Array { if (value !== undefined) { if (value === null) { value = this.EMPTY_TRIE_ROOT @@ -126,7 +124,7 @@ export class Trie { /** * Checks if a given root exists. */ - async checkRoot(root: Buffer): Promise { + async checkRoot(root: Uint8Array): Promise { try { const value = await this.lookupNode(root) return value !== null @@ -143,11 +141,11 @@ export class Trie { * Gets a value given a `key` * @param key - the key to search for * @param throwIfMissing - if true, throws if any nodes are missing. Used for verifying proofs. (default: false) - * @returns A Promise that resolves to `Buffer` if a value was found or `null` if no value was found. + * @returns A Promise that resolves to `Uint8Array` if a value was found or `null` if no value was found. */ - async get(key: Buffer, throwIfMissing = false): Promise { + async get(key: Uint8Array, throwIfMissing = false): Promise { const { node, remaining } = await this.findPath(this.appliedKey(key), throwIfMissing) - let value: Buffer | null = null + let value: Uint8Array | null = null if (node && remaining.length === 0) { value = node.value() } @@ -161,9 +159,9 @@ export class Trie { * @param value * @returns A Promise that resolves once value is stored. */ - async put(key: Buffer, value: Buffer): Promise { - if (this._opts.useRootPersistence && key.equals(ROOT_DB_KEY)) { - throw new Error(`Attempted to set '${ROOT_DB_KEY.toString()}' key but it is not allowed.`) + async put(key: Uint8Array, value: Uint8Array): Promise { + if (this._opts.useRootPersistence && equalsBytes(key, ROOT_DB_KEY) === true) { + throw new Error(`Attempted to set '${bytesToUtf8(ROOT_DB_KEY)}' key but it is not allowed.`) } // If value is empty, delete @@ -173,7 +171,7 @@ export class Trie { await this._lock.acquire() const appliedKey = this.appliedKey(key) - if (this.root().equals(this.EMPTY_TRIE_ROOT)) { + if (equalsBytes(this.root(), this.EMPTY_TRIE_ROOT) === true) { // If no root, initialize this trie await this._createInitialNode(appliedKey, value) } else { @@ -184,7 +182,7 @@ export class Trie { const val = await this.get(key) // Only delete keys if it either does not exist, or if it gets updated // (The update will update the hash of the node, thus we can delete the original leaf node) - if (val === null || !val.equals(value)) { + if (val === null || equalsBytes(val, value) === false) { // All items of the stack are going to change. // (This is the path from the root node to wherever it needs to insert nodes) // The items change, because the leaf value is updated, thus all keyhashes in the @@ -215,7 +213,7 @@ export class Trie { * @param key * @returns A Promise that resolves once value is deleted. */ - async del(key: Buffer): Promise { + async del(key: Uint8Array): Promise { await this._lock.acquire() const appliedKey = this.appliedKey(key) const { node, stack } = await this.findPath(appliedKey) @@ -250,11 +248,11 @@ export class Trie { * @param key - the search key * @param throwIfMissing - if true, throws if any nodes are missing. Used for verifying proofs. (default: false) */ - async findPath(key: Buffer, throwIfMissing = false): Promise { + async findPath(key: Uint8Array, throwIfMissing = false): Promise { // eslint-disable-next-line no-async-promise-executor return new Promise(async (resolve, reject) => { const stack: TrieNode[] = [] - const targetKey = bufferToNibbles(key) + const targetKey = bytesToNibbles(key) const onFound: FoundNodeFunction = async (_, node, keyProgress, walkController) => { if (node === null) { @@ -321,7 +319,7 @@ export class Trie { * @param onFound - callback to call when a node is found. This schedules new tasks. If no tasks are available, the Promise resolves. * @returns Resolves when finished walking trie. */ - async walkTrie(root: Buffer, onFound: FoundNodeFunction): Promise { + async walkTrie(root: Uint8Array, onFound: FoundNodeFunction): Promise { await WalkController.newWalk(onFound, this, root) } @@ -329,8 +327,8 @@ export class Trie { * Creates the initial node from an empty tree. * @private */ - async _createInitialNode(key: Buffer, value: Buffer): Promise { - const newNode = new LeafNode(bufferToNibbles(key), value) + async _createInitialNode(key: Uint8Array, value: Uint8Array): Promise { + const newNode = new LeafNode(bytesToNibbles(key), value) const encoded = newNode.serialize() this.root(this.hash(encoded)) @@ -341,13 +339,13 @@ export class Trie { /** * Retrieves a node from db by hash. */ - async lookupNode(node: Buffer | Buffer[]): Promise { + async lookupNode(node: Uint8Array | Uint8Array[]): Promise { if (isRawNode(node)) { - return decodeRawNode(node as Buffer[]) + return decodeRawNode(node as Uint8Array[]) } let value = null let foundNode = null - value = await this._db.get(node as Buffer) + value = await this._db.get(node as Uint8Array) if (value) { foundNode = decodeNode(value) } else { @@ -366,8 +364,8 @@ export class Trie { * @param stack */ async _updateNode( - k: Buffer, - value: Buffer, + k: Uint8Array, + value: Uint8Array, keyRemainder: Nibbles, stack: TrieNode[] ): Promise { @@ -378,7 +376,7 @@ export class Trie { } // add the new nodes - const key = bufferToNibbles(k) + const key = bytesToNibbles(k) // Check if the last node is a leaf and the key matches to this let matchLeaf = false @@ -468,7 +466,7 @@ export class Trie { * Deletes a node from the trie. * @private */ - async _deleteNode(k: Buffer, stack: TrieNode[]): Promise { + async _deleteNode(k: Uint8Array, stack: TrieNode[]): Promise { const processBranchNode = ( key: Nibbles, branchKey: number, @@ -531,7 +529,7 @@ export class Trie { let parentNode = stack.pop() const opStack: BatchDBOp[] = [] - let key = bufferToNibbles(k) + let key = bytesToNibbles(k) if (!parentNode) { // the root here has to be a leaf. @@ -575,7 +573,7 @@ export class Trie { if (this._opts.useNodePruning) { opStack.push({ type: 'del', - key: branchNode as Buffer, + key: branchNode as Uint8Array, }) } @@ -628,7 +626,7 @@ export class Trie { node.setBranch(branchKey!, lastRoot) } } - lastRoot = this._formatNode(node, stack.length === 0, opStack) as Buffer + lastRoot = this._formatNode(node, stack.length === 0, opStack) as Uint8Array } if (lastRoot) { @@ -653,11 +651,11 @@ export class Trie { topLevel: boolean, opStack: BatchDBOp[], remove: boolean = false - ): Buffer | (EmbeddedNode | null)[] { + ): Uint8Array | (EmbeddedNode | null)[] { const encoded = node.serialize() if (encoded.length >= 32 || topLevel) { - const hashRoot = Buffer.from(this.hash(encoded)) + const hashRoot = this.hash(encoded) if (remove) { if (this._opts.useNodePruning) { @@ -685,11 +683,11 @@ export class Trie { * (delete operations are only executed on DB with `deleteFromDB` set to `true`) * @example * const ops = [ - * { type: 'del', key: Buffer.from('father') } - * , { type: 'put', key: Buffer.from('name'), value: Buffer.from('Yuri Irsenovich Kim') } - * , { type: 'put', key: Buffer.from('dob'), value: Buffer.from('16 February 1941') } - * , { type: 'put', key: Buffer.from('spouse'), value: Buffer.from('Kim Young-sook') } - * , { type: 'put', key: Buffer.from('occupation'), value: Buffer.from('Clown') } + * { type: 'del', key: Uint8Array.from('father') } + * , { type: 'put', key: Uint8Array.from('name'), value: Uint8Array.from('Yuri Irsenovich Kim') } + * , { type: 'put', key: Uint8Array.from('dob'), value: Uint8Array.from('16 February 1941') } + * , { type: 'put', key: Uint8Array.from('spouse'), value: Uint8Array.from('Kim Young-sook') } + * , { type: 'put', key: Uint8Array.from('occupation'), value: Uint8Array.from('Clown') } * ] * await trie.batch(ops) * @param ops @@ -716,7 +714,7 @@ export class Trie { const opStack = proof.map((nodeValue) => { return { type: 'put', - key: Buffer.from(this.hash(nodeValue)), + key: Uint8Array.from(this.hash(nodeValue)), value: nodeValue, } as PutBatch }) @@ -734,7 +732,7 @@ export class Trie { * Creates a proof from a trie and key that can be verified using {@link Trie.verifyProof}. * @param key */ - async createProof(key: Buffer): Promise { + async createProof(key: Uint8Array): Promise { const { stack } = await this.findPath(this.appliedKey(key)) const p = stack.map((stackElem) => { return stackElem.serialize() @@ -750,7 +748,11 @@ export class Trie { * @throws If proof is found to be invalid. * @returns The value from the key, or null if valid proof of non-existence. */ - async verifyProof(rootHash: Buffer, key: Buffer, proof: Proof): Promise { + async verifyProof( + rootHash: Uint8Array, + key: Uint8Array, + proof: Proof + ): Promise { const proofTrie = new Trie({ root: rootHash, useKeyHashingFunction: this._opts.useKeyHashingFunction, @@ -776,18 +778,18 @@ export class Trie { * {@link verifyRangeProof} */ verifyRangeProof( - rootHash: Buffer, - firstKey: Buffer | null, - lastKey: Buffer | null, - keys: Buffer[], - values: Buffer[], - proof: Buffer[] | null + rootHash: Uint8Array, + firstKey: Uint8Array | null, + lastKey: Uint8Array | null, + keys: Uint8Array[], + values: Uint8Array[], + proof: Uint8Array[] | null ): Promise { return verifyRangeProof( rootHash, - firstKey && bufferToNibbles(this.appliedKey(firstKey)), - lastKey && bufferToNibbles(this.appliedKey(lastKey)), - keys.map((k) => this.appliedKey(k)).map(bufferToNibbles), + firstKey && bytesToNibbles(this.appliedKey(firstKey)), + lastKey && bytesToNibbles(this.appliedKey(lastKey)), + keys.map((k) => this.appliedKey(k)).map(bytesToNibbles), values, proof, this._opts.useKeyHashingFunction @@ -799,7 +801,7 @@ export class Trie { // (i.e. the Trie is not correctly pruned) // If this method returns `true`, the Trie is correctly pruned and all keys are reachable async verifyPrunedIntegrity(): Promise { - const roots = [this.root().toString('hex'), this.appliedKey(ROOT_DB_KEY).toString('hex')] + const roots = [bytesToHex(this.root()), bytesToHex(this.appliedKey(ROOT_DB_KEY))] for (const dbkey of (this)._db.db._database.keys()) { if (roots.includes(dbkey)) { // The root key can never be found from the trie, otherwise this would @@ -818,7 +820,7 @@ export class Trie { if (node instanceof BranchNode) { for (const item of node._branches) { // If one of the branches matches the key, then it is found - if (item && item.toString('hex') === dbkey) { + if (item !== null && bytesToHex(item as Uint8Array) === dbkey) { found = true return } @@ -828,7 +830,7 @@ export class Trie { } if (node instanceof ExtensionNode) { // If the value of the ExtensionNode points to the dbkey, then it is found - if (node.value().toString('hex') === dbkey) { + if (bytesToHex(node.value()) === dbkey) { found = true return } @@ -846,7 +848,7 @@ export class Trie { } /** - * The `data` event is given an `Object` that has two properties; the `key` and the `value`. Both should be Buffers. + * The `data` event is given an `Object` that has two properties; the `key` and the `value`. Both should be Uint8Arrays. * @return Returns a [stream](https://nodejs.org/dist/latest-v12.x/docs/api/stream.html#stream_class_stream_readable) of the contents of the `trie` */ createReadStream(): ReadStream { @@ -902,15 +904,15 @@ export class Trie { * depending on the `useKeyHashing` option being set or not. * @param key */ - protected appliedKey(key: Buffer) { + protected appliedKey(key: Uint8Array) { if (this._opts.useKeyHashing) { return this.hash(key) } return key } - protected hash(msg: Uint8Array): Buffer { - return Buffer.from(this._opts.useKeyHashingFunction(msg)) + protected hash(msg: Uint8Array): Uint8Array { + return Uint8Array.from(this._opts.useKeyHashingFunction(msg)) } /** diff --git a/packages/trie/src/types.ts b/packages/trie/src/types.ts index 5a73e08b58..68cb4cd0c0 100644 --- a/packages/trie/src/types.ts +++ b/packages/trie/src/types.ts @@ -1,3 +1,5 @@ +import { utf8ToBytes } from 'ethereum-cryptography/utils' + import type { BranchNode, ExtensionNode, LeafNode } from './trie' import type { WalkController } from './util/walkController' @@ -7,12 +9,12 @@ export type Nibbles = number[] // Branch and extension nodes might store // hash to next node, or embed it if its len < 32 -export type EmbeddedNode = Buffer | Buffer[] +export type EmbeddedNode = Uint8Array | Uint8Array[] -export type Proof = Buffer[] +export type Proof = Uint8Array[] export type FoundNodeFunction = ( - nodeRef: Buffer, + nodeRef: Uint8Array, node: TrieNode | null, key: Nibbles, walkController: WalkController @@ -27,9 +29,9 @@ export interface TrieOpts { db?: DB /** - * A `Buffer` for the root of a previously stored trie + * A `Uint8Array` for the root of a previously stored trie */ - root?: Buffer + root?: Uint8Array /** * Create as a secure Trie where the keys are automatically hashed using the @@ -73,35 +75,35 @@ export type BatchDBOp = PutBatch | DelBatch export interface PutBatch { type: 'put' - key: Buffer - value: Buffer + key: Uint8Array + value: Uint8Array } export interface DelBatch { type: 'del' - key: Buffer + key: Uint8Array } export interface DB { /** * Retrieves a raw value from leveldb. * @param key - * @returns A Promise that resolves to `Buffer` if a value is found or `null` if no value is found. + * @returns A Promise that resolves to `Uint8Array` if a value is found or `null` if no value is found. */ - get(key: Buffer): Promise + get(key: Uint8Array): Promise /** * Writes a value directly to leveldb. - * @param key The key as a `Buffer` + * @param key The key as a `Uint8Array` * @param value The value to be stored */ - put(key: Buffer, val: Buffer): Promise + put(key: Uint8Array, val: Uint8Array): Promise /** * Removes a raw value in the underlying leveldb. * @param keys */ - del(key: Buffer): Promise + del(key: Uint8Array): Promise /** * Performs a batch operation on db. @@ -117,10 +119,10 @@ export interface DB { } export type Checkpoint = { - // We cannot use a Buffer => Buffer map directly. If you create two Buffers with the same internal value, + // We cannot use a Uint8Array => Uint8Array map directly. If you create two Uint8Arrays with the same internal value, // then when setting a value on the Map, it actually creates two indices. - keyValueMap: Map - root: Buffer + keyValueMap: Map + root: Uint8Array } -export const ROOT_DB_KEY = Buffer.from('__root__') +export const ROOT_DB_KEY = utf8ToBytes('__root__') diff --git a/packages/trie/src/util/nibbles.ts b/packages/trie/src/util/nibbles.ts index fd7fbefc5d..944909d17b 100644 --- a/packages/trie/src/util/nibbles.ts +++ b/packages/trie/src/util/nibbles.ts @@ -1,13 +1,15 @@ +import { toBytes } from '@ethereumjs/util' + import type { Nibbles } from '../types' /** - * Converts a buffer to a nibble array. + * Converts a bytes to a nibble array. * @private * @param key */ -export function bufferToNibbles(key: Buffer): Nibbles { - const bkey = Buffer.from(key) - const nibbles = [] as any +export function bytesToNibbles(key: Uint8Array): Nibbles { + const bkey = toBytes(key) + const nibbles = [] as Nibbles for (let i = 0; i < bkey.length; i++) { let q = i * 2 @@ -20,12 +22,12 @@ export function bufferToNibbles(key: Buffer): Nibbles { } /** - * Converts a nibble array into a buffer. + * Converts a nibble array into bytes. * @private * @param arr - Nibble array */ -export function nibblesToBuffer(arr: Nibbles): Buffer { - const buf = Buffer.alloc(arr.length / 2) +export function nibblestoBytes(arr: Nibbles): Uint8Array { + const buf = new Uint8Array(arr.length / 2) for (let i = 0; i < buf.length; i++) { let q = i * 2 buf[i] = (arr[q] << 4) + arr[++q] diff --git a/packages/trie/src/util/readStream.ts b/packages/trie/src/util/readStream.ts index 76d31f4986..70ea90cf2c 100644 --- a/packages/trie/src/util/readStream.ts +++ b/packages/trie/src/util/readStream.ts @@ -2,7 +2,7 @@ import { Readable } from 'readable-stream' import { BranchNode, LeafNode } from '../trie' -import { nibblesToBuffer } from './nibbles' +import { nibblestoBytes } from './nibbles' import type { Trie } from '../trie' import type { FoundNodeFunction } from '../types' @@ -27,7 +27,7 @@ export class TrieReadStream extends Readable { await this._findValueNodes(async (_, node, key, walkController) => { if (node !== null) { this.push({ - key: nibblesToBuffer(key), + key: nibblestoBytes(key), value: node.value(), }) walkController.allChildren(node, key) diff --git a/packages/trie/src/util/walkController.ts b/packages/trie/src/util/walkController.ts index 9d0301f534..12b566e1ec 100644 --- a/packages/trie/src/util/walkController.ts +++ b/packages/trie/src/util/walkController.ts @@ -39,14 +39,14 @@ export class WalkController { static async newWalk( onNode: FoundNodeFunction, trie: Trie, - root: Buffer, + root: Uint8Array, poolSize?: number ): Promise { const strategy = new WalkController(onNode, trie, poolSize ?? 500) await strategy.startWalk(root) } - private async startWalk(root: Buffer): Promise { + private async startWalk(root: Uint8Array): Promise { // eslint-disable-next-line no-async-promise-executor return new Promise(async (resolve, reject) => { this.resolve = resolve @@ -81,7 +81,7 @@ export class WalkController { } for (const child of children) { const keyExtension = child[0] as Nibbles - const childRef = child[1] as Buffer + const childRef = child[1] as Uint8Array const childKey = key.concat(keyExtension) const priority = childKey.length this.pushNodeToQueue(childRef, childKey, priority) @@ -94,7 +94,7 @@ export class WalkController { * @param key - The current key. * @param priority - Optional priority, defaults to key length */ - pushNodeToQueue(nodeRef: Buffer, key: Nibbles = [], priority?: number) { + pushNodeToQueue(nodeRef: Uint8Array, key: Nibbles = [], priority?: number) { this.taskExecutor.executeOrQueue( priority ?? key.length, async (taskFinishedCallback: Function) => { @@ -105,7 +105,7 @@ export class WalkController { return this.reject(error) } taskFinishedCallback() // this marks the current task as finished. If there are any tasks left in the queue, this will immediately execute the first task. - this.processNode(nodeRef as Buffer, childNode as TrieNode, key) + this.processNode(nodeRef as Uint8Array, childNode as TrieNode, key) } ) } @@ -128,10 +128,10 @@ export class WalkController { const childKey = key.slice() // This copies the key to a new array. childKey.push(childIndex) const prio = priority ?? childKey.length - this.pushNodeToQueue(childRef as Buffer, childKey, prio) + this.pushNodeToQueue(childRef as Uint8Array, childKey, prio) } - private processNode(nodeRef: Buffer, node: TrieNode | null, key: Nibbles = []) { + private processNode(nodeRef: Uint8Array, node: TrieNode | null, key: Nibbles = []) { this.onNode(nodeRef, node, key, this) if (this.taskExecutor.finished()) { // onNode should schedule new tasks. If no tasks was added and the queue is empty, then we have finished our walk. diff --git a/packages/trie/test/db/checkpoint.spec.ts b/packages/trie/test/db/checkpoint.spec.ts index d164de487b..8514d2078b 100644 --- a/packages/trie/test/db/checkpoint.spec.ts +++ b/packages/trie/test/db/checkpoint.spec.ts @@ -1,3 +1,4 @@ +import { hexStringToBytes, utf8ToBytes } from '@ethereumjs/util' import * as tape from 'tape' import { CheckpointDB, MapDB } from '../../src' @@ -5,14 +6,14 @@ import { CheckpointDB, MapDB } from '../../src' import type { BatchDBOp } from '../../src' tape('DB tests', (t) => { - const k = Buffer.from('k1') - const v = Buffer.from('v1') - const v2 = Buffer.from('v2') - const v3 = Buffer.from('v3') + const k = utf8ToBytes('k1') + const v = utf8ToBytes('v1') + const v2 = utf8ToBytes('v2') + const v3 = utf8ToBytes('v3') t.test('Checkpointing: revert -> put (add)', async (st) => { const db = new CheckpointDB(new MapDB()) - db.checkpoint(Buffer.from('1', 'hex')) + db.checkpoint(hexStringToBytes('01')) await db.put(k, v) st.deepEqual(await db.get(k), v, 'before revert: v1') await db.revert() @@ -24,7 +25,7 @@ tape('DB tests', (t) => { const db = new CheckpointDB(new MapDB()) await db.put(k, v) st.deepEqual(await db.get(k), v, 'before CP: v1') - db.checkpoint(Buffer.from('1', 'hex')) + db.checkpoint(hexStringToBytes('01')) await db.put(k, v2) await db.put(k, v3) await db.revert() @@ -36,7 +37,7 @@ tape('DB tests', (t) => { const db = new CheckpointDB(new MapDB()) await db.put(k, v) st.deepEqual(await db.get(k), v, 'before CP: v1') - db.checkpoint(Buffer.from('1', 'hex')) + db.checkpoint(hexStringToBytes('01')) const ops = [ { type: 'put', key: k, value: v2 }, { type: 'put', key: k, value: v3 }, @@ -51,7 +52,7 @@ tape('DB tests', (t) => { const db = new CheckpointDB(new MapDB()) await db.put(k, v) st.deepEqual(await db.get(k), v, 'before CP: v1') - db.checkpoint(Buffer.from('1', 'hex')) + db.checkpoint(hexStringToBytes('01')) await db.del(k) st.deepEqual(await db.get(k), null, 'before revert: null') await db.revert() @@ -62,10 +63,11 @@ tape('DB tests', (t) => { t.test('Checkpointing: nested checkpoints -> commit -> revert', async (st) => { const db = new CheckpointDB(new MapDB()) await db.put(k, v) + st.deepEqual(await db.get(k), v, 'before CP: v1') - db.checkpoint(Buffer.from('1', 'hex')) + db.checkpoint(hexStringToBytes('01')) await db.put(k, v2) - db.checkpoint(Buffer.from('2', 'hex')) + db.checkpoint(hexStringToBytes('02')) await db.put(k, v3) await db.commit() st.deepEqual(await db.get(k), v3, 'after commit (second CP): v3') diff --git a/packages/trie/test/db/db.spec.ts b/packages/trie/test/db/db.spec.ts index 5798e9dedd..0f3f1969e5 100644 --- a/packages/trie/test/db/db.spec.ts +++ b/packages/trie/test/db/db.spec.ts @@ -1,3 +1,4 @@ +import { equalsBytes, utf8ToBytes } from '@ethereumjs/util' import * as tape from 'tape' import { MapDB } from '../../src' @@ -7,15 +8,15 @@ import type { BatchDBOp } from '../../src' tape('DB tests', (t) => { const db = new MapDB() - const k = Buffer.from('k1') - const v = Buffer.from('v1') - const k2 = Buffer.from('k2') - const v2 = Buffer.from('v2') + const k = utf8ToBytes('k1') + const v = utf8ToBytes('v1') + const k2 = utf8ToBytes('k2') + const v2 = utf8ToBytes('v2') t.test('Operations: puts and gets value', async (st) => { await db.put(k, v) const res = await db.get(k) - st.ok(v.equals(res!)) + st.ok(equalsBytes(v, res!)) st.end() }) @@ -33,7 +34,7 @@ tape('DB tests', (t) => { ] as BatchDBOp[] await db.batch(ops) const res = await db.get(k2) - st.ok(v2.equals(res!)) + st.ok(equalsBytes(v2, res!)) st.end() }) }) diff --git a/packages/trie/test/encoding.spec.ts b/packages/trie/test/encoding.spec.ts index a55b8ea874..84c3d19b18 100644 --- a/packages/trie/test/encoding.spec.ts +++ b/packages/trie/test/encoding.spec.ts @@ -1,4 +1,4 @@ -import { toBuffer } from '@ethereumjs/util' +import { bytesToHex, hexStringToBytes, toBytes, utf8ToBytes } from '@ethereumjs/util' import * as tape from 'tape' import { Trie } from '../src' @@ -8,8 +8,8 @@ const trie2 = new Trie() const hex = 'FF44A3B3' tape('encoding hex prefixes', async function (t) { - await trie.put(Buffer.from(hex, 'hex'), Buffer.from('test')) - await trie2.put(toBuffer(`0x${hex}`), Buffer.from('test')) - t.equal(trie.root().toString('hex'), trie2.root().toString('hex')) + await trie.put(hexStringToBytes(hex), utf8ToBytes('test')) + await trie2.put(toBytes(`0x${hex}`), utf8ToBytes('test')) + t.equal(bytesToHex(trie.root()), bytesToHex(trie2.root())) t.end() }) diff --git a/packages/trie/test/index.spec.ts b/packages/trie/test/index.spec.ts index c4f97e3d14..65b7ab0544 100644 --- a/packages/trie/test/index.spec.ts +++ b/packages/trie/test/index.spec.ts @@ -1,14 +1,18 @@ -// explicitly import buffer, -// needed for karma-typescript bundling import { RLP } from '@ethereumjs/rlp' -import { KECCAK256_NULL, KECCAK256_RLP_S, bufArrToArr } from '@ethereumjs/util' -import { Buffer } from 'buffer' +import { + KECCAK256_NULL, + KECCAK256_RLP_S, + bytesToHex, + hexStringToBytes, + utf8ToBytes, +} from '@ethereumjs/util' import { blake2b } from 'ethereum-cryptography/blake2b' import { keccak256 } from 'ethereum-cryptography/keccak' +import { bytesToUtf8, concatBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' import { LeafNode, Trie } from '../src' -import { bufferToNibbles } from '../src/util/nibbles' +import { bytesToNibbles } from '../src/util/nibbles' import type { HashKeysFunction } from '../src' @@ -16,12 +20,12 @@ tape('simple save and retrieve', function (tester) { const it = tester.test it('should not crash if given a non-existent root', async function (t) { - const root = Buffer.from( - '3f4399b08efe68945c1cf90ffe85bbe3ce978959da753f9e649f034015b8817d', - 'hex' + const root = hexStringToBytes( + '3f4399b08efe68945c1cf90ffe85bbe3ce978959da753f9e649f034015b8817d' ) + const trie = new Trie({ root }) - const value = await trie.get(Buffer.from('test')) + const value = await trie.get(utf8ToBytes('test')) t.equal(value, null) t.end() }) @@ -29,59 +33,60 @@ tape('simple save and retrieve', function (tester) { const trie = new Trie() it('save a value', async function (t) { - await trie.put(Buffer.from('test'), Buffer.from('one')) + await trie.put(utf8ToBytes('test'), utf8ToBytes('one')) t.end() }) it('should get a value', async function (t) { - const value = await trie.get(Buffer.from('test')) - t.equal(value!.toString(), 'one') + const value = await trie.get(utf8ToBytes('test')) + t.equal(bytesToUtf8(value!), 'one') t.end() }) it('should update a value', async function (t) { - await trie.put(Buffer.from('test'), Buffer.from('two')) - const value = await trie.get(Buffer.from('test')) - t.equal(value!.toString(), 'two') + await trie.put(utf8ToBytes('test'), utf8ToBytes('two')) + const value = await trie.get(utf8ToBytes('test')) + + t.equal(bytesToUtf8(value!), 'two') t.end() }) it('should delete a value', async function (t) { - await trie.del(Buffer.from('test')) - const value = await trie.get(Buffer.from('test')) + await trie.del(utf8ToBytes('test')) + const value = await trie.get(utf8ToBytes('test')) t.notok(value) t.end() }) it('should recreate a value', async function (t) { - await trie.put(Buffer.from('test'), Buffer.from('one')) + await trie.put(utf8ToBytes('test'), utf8ToBytes('one')) t.end() }) it('should get updated a value', async function (t) { - const value = await trie.get(Buffer.from('test')) - t.equal(value!.toString(), 'one') + const value = await trie.get(utf8ToBytes('test')) + t.equal(bytesToUtf8(value!), 'one') t.end() }) it('should create a branch here', async function (t) { - await trie.put(Buffer.from('doge'), Buffer.from('coin')) + await trie.put(utf8ToBytes('doge'), utf8ToBytes('coin')) t.equal( 'de8a34a8c1d558682eae1528b47523a483dd8685d6db14b291451a66066bf0fc', - trie.root().toString('hex') + bytesToHex(trie.root()) ) t.end() }) it('should get a value that is in a branch', async function (t) { - const value = await trie.get(Buffer.from('doge')) - t.equal(value!.toString(), 'coin') + const value = await trie.get(utf8ToBytes('doge')) + t.equal(bytesToUtf8(value!), 'coin') t.end() }) it('should delete from a branch', async function (t) { - await trie.del(Buffer.from('doge')) - const value = await trie.get(Buffer.from('doge')) + await trie.del(utf8ToBytes('doge')) + const value = await trie.get(utf8ToBytes('doge')) t.equal(value, null) t.end() }) @@ -93,20 +98,20 @@ tape('simple save and retrieve', function (tester) { const longStringRoot = 'b173e2db29e79c78963cff5196f8a983fbe0171388972106b114ef7f5c24dfa3' it('should store a longer string', async function (t) { - await trie.put(Buffer.from('done'), Buffer.from(longString)) - await trie.put(Buffer.from('doge'), Buffer.from('coin')) - t.equal(longStringRoot, trie.root().toString('hex')) + await trie.put(utf8ToBytes('done'), utf8ToBytes(longString)) + await trie.put(utf8ToBytes('doge'), utf8ToBytes('coin')) + t.equal(longStringRoot, bytesToHex(trie.root())) t.end() }) it('should retrieve a longer value', async function (t) { - const value = await trie.get(Buffer.from('done')) - t.equal(value!.toString(), longString) + const value = await trie.get(utf8ToBytes('done')) + t.equal(bytesToUtf8(value!), longString) t.end() }) it('should when being modified delete the old value', async function (t) { - await trie.put(Buffer.from('done'), Buffer.from('test')) + await trie.put(utf8ToBytes('done'), utf8ToBytes('test')) t.end() }) }) @@ -116,24 +121,24 @@ tape('simple save and retrieve', function (tester) { const trie = new Trie() it('should store a value', async function (t) { - await trie.put(Buffer.from('doge'), Buffer.from('coin')) + await trie.put(utf8ToBytes('doge'), utf8ToBytes('coin')) t.end() }) it('should create extension to store this value', async function (t) { - await trie.put(Buffer.from('do'), Buffer.from('verb')) + await trie.put(utf8ToBytes('do'), utf8ToBytes('verb')) t.equal( 'f803dfcb7e8f1afd45e88eedb4699a7138d6c07b71243d9ae9bff720c99925f9', - trie.root().toString('hex') + bytesToHex(trie.root()) ) t.end() }) it('should store this value under the extension', async function (t) { - await trie.put(Buffer.from('done'), Buffer.from('finished')) + await trie.put(utf8ToBytes('done'), utf8ToBytes('finished')) t.equal( '409cff4d820b394ed3fb1cd4497bdd19ffa68d30ae34157337a7043c94a3e8cb', - trie.root().toString('hex') + bytesToHex(trie.root()) ) t.end() }) @@ -144,20 +149,20 @@ tape('simple save and retrieve', function (tester) { const trie = new Trie() it('should create extension to store this value', async function (t) { - await trie.put(Buffer.from('do'), Buffer.from('verb')) + await trie.put(utf8ToBytes('do'), utf8ToBytes('verb')) t.end() }) it('should store a value', async function (t) { - await trie.put(Buffer.from('doge'), Buffer.from('coin')) + await trie.put(utf8ToBytes('doge'), utf8ToBytes('coin')) t.end() }) it('should store this value under the extension', async function (t) { - await trie.put(Buffer.from('done'), Buffer.from('finished')) + await trie.put(utf8ToBytes('done'), utf8ToBytes('finished')) t.equal( '409cff4d820b394ed3fb1cd4497bdd19ffa68d30ae34157337a7043c94a3e8cb', - trie.root().toString('hex') + bytesToHex(trie.root()) ) t.end() }) @@ -172,51 +177,51 @@ tape('testing deletion cases', function (tester) { } it('should delete from a branch->branch-branch', async function (t) { - await trieSetup.trie.put(Buffer.from([11, 11, 11]), Buffer.from('first')) - await trieSetup.trie.put(Buffer.from([12, 22, 22]), Buffer.from('create the first branch')) - await trieSetup.trie.put(Buffer.from([12, 34, 44]), Buffer.from('create the last branch')) + await trieSetup.trie.put(new Uint8Array([11, 11, 11]), utf8ToBytes('first')) + await trieSetup.trie.put(new Uint8Array([12, 22, 22]), utf8ToBytes('create the first branch')) + await trieSetup.trie.put(new Uint8Array([12, 34, 44]), utf8ToBytes('create the last branch')) - await trieSetup.trie.del(Buffer.from([12, 22, 22])) - const val = await trieSetup.trie.get(Buffer.from([12, 22, 22])) + await trieSetup.trie.del(new Uint8Array([12, 22, 22])) + const val = await trieSetup.trie.get(new Uint8Array([12, 22, 22])) t.equal(null, val, trieSetup.msg) t.end() }) it('should delete from a branch->branch-extension', async function (t) { - await trieSetup.trie.put(Buffer.from([11, 11, 11]), Buffer.from('first')) - await trieSetup.trie.put(Buffer.from([12, 22, 22]), Buffer.from('create the first branch')) - await trieSetup.trie.put(Buffer.from([12, 33, 33]), Buffer.from('create the middle branch')) - await trieSetup.trie.put(Buffer.from([12, 34, 44]), Buffer.from('create the last branch')) + await trieSetup.trie.put(new Uint8Array([11, 11, 11]), utf8ToBytes('first')) + await trieSetup.trie.put(new Uint8Array([12, 22, 22]), utf8ToBytes('create the first branch')) + await trieSetup.trie.put(new Uint8Array([12, 33, 33]), utf8ToBytes('create the middle branch')) + await trieSetup.trie.put(new Uint8Array([12, 34, 44]), utf8ToBytes('create the last branch')) - await trieSetup.trie.del(Buffer.from([12, 22, 22])) - const val = await trieSetup.trie.get(Buffer.from([12, 22, 22])) + await trieSetup.trie.del(new Uint8Array([12, 22, 22])) + const val = await trieSetup.trie.get(new Uint8Array([12, 22, 22])) t.equal(null, val, trieSetup.msg) t.end() }) it('should delete from a extension->branch-extension', async function (t) { - await trieSetup.trie.put(Buffer.from([11, 11, 11]), Buffer.from('first')) - await trieSetup.trie.put(Buffer.from([12, 22, 22]), Buffer.from('create the first branch')) - await trieSetup.trie.put(Buffer.from([12, 33, 33]), Buffer.from('create the middle branch')) - await trieSetup.trie.put(Buffer.from([12, 34, 44]), Buffer.from('create the last branch')) + await trieSetup.trie.put(new Uint8Array([11, 11, 11]), utf8ToBytes('first')) + await trieSetup.trie.put(new Uint8Array([12, 22, 22]), utf8ToBytes('create the first branch')) + await trieSetup.trie.put(new Uint8Array([12, 33, 33]), utf8ToBytes('create the middle branch')) + await trieSetup.trie.put(new Uint8Array([12, 34, 44]), utf8ToBytes('create the last branch')) // delete the middle branch - await trieSetup.trie.del(Buffer.from([11, 11, 11])) - const val = await trieSetup.trie.get(Buffer.from([11, 11, 11])) + await trieSetup.trie.del(new Uint8Array([11, 11, 11])) + const val = await trieSetup.trie.get(new Uint8Array([11, 11, 11])) t.equal(null, val, trieSetup.msg) t.end() }) it('should delete from a extension->branch-branch', async function (t) { - await trieSetup.trie.put(Buffer.from([11, 11, 11]), Buffer.from('first')) - await trieSetup.trie.put(Buffer.from([12, 22, 22]), Buffer.from('create the first branch')) - await trieSetup.trie.put(Buffer.from([12, 33, 33]), Buffer.from('create the middle branch')) - await trieSetup.trie.put(Buffer.from([12, 34, 44]), Buffer.from('create the last branch')) + await trieSetup.trie.put(new Uint8Array([11, 11, 11]), utf8ToBytes('first')) + await trieSetup.trie.put(new Uint8Array([12, 22, 22]), utf8ToBytes('create the first branch')) + await trieSetup.trie.put(new Uint8Array([12, 33, 33]), utf8ToBytes('create the middle branch')) + await trieSetup.trie.put(new Uint8Array([12, 34, 44]), utf8ToBytes('create the last branch')) // delete the middle branch - await trieSetup.trie.del(Buffer.from([11, 11, 11])) - const val = await trieSetup.trie.get(Buffer.from([11, 11, 11])) + await trieSetup.trie.del(new Uint8Array([11, 11, 11])) + const val = await trieSetup.trie.get(new Uint8Array([11, 11, 11])) t.equal(null, val, trieSetup.msg) t.end() @@ -225,9 +230,9 @@ tape('testing deletion cases', function (tester) { tape('shall handle the case of node not found correctly', async (t) => { const trie = new Trie() - await trie.put(Buffer.from('a'), Buffer.from('value1')) - await trie.put(Buffer.from('aa'), Buffer.from('value2')) - await trie.put(Buffer.from('aaa'), Buffer.from('value3')) + await trie.put(utf8ToBytes('a'), utf8ToBytes('value1')) + await trie.put(utf8ToBytes('aa'), utf8ToBytes('value2')) + await trie.put(utf8ToBytes('aaa'), utf8ToBytes('value3')) /* Setups a trie which consists of ExtensionNode -> @@ -237,15 +242,15 @@ tape('shall handle the case of node not found correctly', async (t) => { LeafNode -> value3 */ - let path = await trie.findPath(Buffer.from('aaa')) + let path = await trie.findPath(utf8ToBytes('aaa')) t.ok(path.node !== null, 'findPath should find a node') - const { stack } = await trie.findPath(Buffer.from('aaa')) + const { stack } = await trie.findPath(utf8ToBytes('aaa')) // @ts-expect-error - await trie._db.del(Buffer.from(keccak256(stack[1].serialize()))) // delete the BranchNode -> value1 from the DB + await trie._db.del(keccak256(stack[1].serialize())) // delete the BranchNode -> value1 from the DB - path = await trie.findPath(Buffer.from('aaa')) + path = await trie.findPath(utf8ToBytes('aaa')) t.ok(path.node === null, 'findPath should not return a node now') t.ok( @@ -260,50 +265,49 @@ tape('it should create the genesis state root from ethereum', function (tester) const it = tester.test const trie4 = new Trie() - const g = Buffer.from('8a40bfaa73256b60764c1bf40675a99083efb075', 'hex') - const j = Buffer.from('e6716f9544a56c530d868e4bfbacb172315bdead', 'hex') - const v = Buffer.from('1e12515ce3e0f817a4ddef9ca55788a1d66bd2df', 'hex') - const a = Buffer.from('1a26338f0d905e295fccb71fa9ea849ffa12aaf4', 'hex') + const g = hexStringToBytes('8a40bfaa73256b60764c1bf40675a99083efb075') + const j = hexStringToBytes('e6716f9544a56c530d868e4bfbacb172315bdead') + const v = hexStringToBytes('1e12515ce3e0f817a4ddef9ca55788a1d66bd2df') + const a = hexStringToBytes('1a26338f0d905e295fccb71fa9ea849ffa12aaf4') - const storageRoot = Buffer.alloc(32) + const storageRoot = new Uint8Array(32) storageRoot.fill(0) - const startAmount = Buffer.alloc(26) + const startAmount = new Uint8Array(26) startAmount.fill(0) startAmount[0] = 1 const account = [startAmount, 0, storageRoot, KECCAK256_NULL] - const rlpAccount = Buffer.from(RLP.encode(bufArrToArr(account as Buffer[]))) + const rlpAccount = RLP.encode(account) const cppRlp = 'f85e9a010000000000000000000000000000000000000000000000000080a00000000000000000000000000000000000000000000000000000000000000000a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470' const genesisStateRoot = '2f4399b08efe68945c1cf90ffe85bbe3ce978959da753f9e649f034015b8817d' - tester.equal(cppRlp, rlpAccount.toString('hex')) + tester.equal(cppRlp, bytesToHex(rlpAccount)) it('shall match the root', async function (t) { await trie4.put(g, rlpAccount) await trie4.put(j, rlpAccount) await trie4.put(v, rlpAccount) await trie4.put(a, rlpAccount) - t.equal(trie4.root().toString('hex'), genesisStateRoot) + t.equal(bytesToHex(trie4.root()), genesisStateRoot) t.end() }) }) tape('setting back state root (deleteFromDB)', async (t) => { - const k1 = Buffer.from('1') + const k1 = utf8ToBytes('1') /* Testing with longer value due to `rlpNode.length >= 32` check in `_formatNode()` * Reasoning from https://ethereum.org/en/developers/docs/data-structures-and-encoding/patricia-merkle-trie/: * "When one node is referenced inside another node, what is included is `H(rlp.encode(x))`, * where `H(x) = sha3(x) if len(x) >= 32 else x`" */ - const v1 = Buffer.from('this-is-some-longer-value-to-test-the-delete-operation-value1') - const k2 = Buffer.from('2') - const v2 = Buffer.from('this-is-some-longer-value-to-test-the-delete-operation-value2') + const v1 = utf8ToBytes('this-is-some-longer-value-to-test-the-delete-operation-value1') + const k2 = utf8ToBytes('2') + const v2 = utf8ToBytes('this-is-some-longer-value-to-test-the-delete-operation-value2') - const rootAfterK1 = Buffer.from( - '809e75931f394603657e113eb7244794f35b8d326cff99407111d600722e9425', - 'hex' + const rootAfterK1 = hexStringToBytes( + '809e75931f394603657e113eb7244794f35b8d326cff99407111d600722e9425' ) const trieSetup = { @@ -331,30 +335,28 @@ tape('dummy hash', async (t) => { const useKeyHashingFunction: HashKeysFunction = (msg) => { const hashLen = 32 if (msg.length <= hashLen - 5) { - return Buffer.concat([Buffer.from('hash_'), Buffer.alloc(hashLen - msg.length, 0), msg]) + return concatBytes(utf8ToBytes('hash_'), new Uint8Array(hashLen - msg.length).fill(0), msg) } else { - return Buffer.concat([Buffer.from('hash_'), msg.slice(0, hashLen - 5)]) + return concatBytes(utf8ToBytes('hash_'), msg.slice(0, hashLen - 5)) } } - const [k, v] = [Buffer.from('foo'), Buffer.from('bar')] - const expectedRoot = Buffer.from( - useKeyHashingFunction(new LeafNode(bufferToNibbles(k), v).serialize()) - ) + const [k, v] = [utf8ToBytes('foo'), utf8ToBytes('bar')] + const expectedRoot = useKeyHashingFunction(new LeafNode(bytesToNibbles(k), v).serialize()) const trie = new Trie({ useKeyHashingFunction }) await trie.put(k, v) - t.equal(trie.root().toString('hex'), expectedRoot.toString('hex')) + t.equal(bytesToHex(trie.root()), bytesToHex(expectedRoot)) t.end() }) tape('blake2b256 trie root', async (t) => { const trie = new Trie({ useKeyHashingFunction: (msg) => blake2b(msg, 32) }) - await trie.put(Buffer.from('foo'), Buffer.from('bar')) + await trie.put(utf8ToBytes('foo'), utf8ToBytes('bar')) t.equal( - trie.root().toString('hex'), + bytesToHex(trie.root()), 'e118db4e01512253df38daafa16fc1d69e03e755595b5847d275d7404ebdc74a' ) t.end() @@ -363,6 +365,6 @@ tape('blake2b256 trie root', async (t) => { tape('empty root', async (t) => { const trie = new Trie() - t.equal(trie.root().toString('hex'), KECCAK256_RLP_S) + t.equal(bytesToHex(trie.root()), KECCAK256_RLP_S) t.end() }) diff --git a/packages/trie/test/official.spec.ts b/packages/trie/test/official.spec.ts index 5d93fc4c57..141c315a46 100644 --- a/packages/trie/test/official.spec.ts +++ b/packages/trie/test/official.spec.ts @@ -1,3 +1,4 @@ +import { bytesToPrefixedHexString, hexStringToBytes, utf8ToBytes } from '@ethereumjs/util' import * as tape from 'tape' import { Trie } from '../src' @@ -12,15 +13,15 @@ tape('official tests', async function (t) { const expect = jsonTests[testName].root for (const input of inputs) { for (let i = 0; i < 2; i++) { - if (input[i] !== undefined && input[i] !== null && input[i].slice(0, 2) === '0x') { - input[i] = Buffer.from(input[i].slice(2), 'hex') + if (typeof input[i] === 'string' && input[i].slice(0, 2) === '0x') { + input[i] = hexStringToBytes(input[i]) } else if (typeof input[i] === 'string') { - input[i] = Buffer.from(input[i]) + input[i] = utf8ToBytes(input[i]) } - await trie.put(Buffer.from(input[0]), input[1]) + await trie.put(input[0], input[1]) } } - t.equal('0x' + trie.root().toString('hex'), expect) + t.equal(bytesToPrefixedHexString(trie.root()), expect) trie = new Trie() } t.end() @@ -37,17 +38,21 @@ tape('official tests any order', async function (t) { for (key of keys) { let val = test.in[key] - if (key.slice(0, 2) === '0x') { - key = Buffer.from(key.slice(2), 'hex') + if (typeof key === 'string' && key.slice(0, 2) === '0x') { + key = hexStringToBytes(key) + } else if (typeof key === 'string') { + key = utf8ToBytes(key) } - if (val !== undefined && val !== null && val.slice(0, 2) === '0x') { - val = Buffer.from(val.slice(2), 'hex') + if (typeof val === 'string' && val.slice(0, 2) === '0x') { + val = hexStringToBytes(val) + } else if (typeof val === 'string') { + val = utf8ToBytes(val) } - await trie.put(Buffer.from(key), Buffer.from(val)) + await trie.put(key, val) } - t.equal('0x' + trie.root().toString('hex'), test.root) + t.equal(bytesToPrefixedHexString(trie.root()), test.root) trie = new Trie() } t.end() diff --git a/packages/trie/test/proof.spec.ts b/packages/trie/test/proof.spec.ts index fd20d4795a..34cef14b28 100644 --- a/packages/trie/test/proof.spec.ts +++ b/packages/trie/test/proof.spec.ts @@ -1,3 +1,4 @@ +import { bytesToUtf8, utf8ToBytes } from '@ethereumjs/util' import * as tape from 'tape' import { Trie } from '../src' @@ -8,52 +9,52 @@ tape('simple merkle proofs generation and verification', function (tester) { it('create a merkle proof and verify it', async (t) => { const trie = new Trie() - await trie.put(Buffer.from('key1aa'), Buffer.from('0123456789012345678901234567890123456789xx')) - await trie.put(Buffer.from('key2bb'), Buffer.from('aval2')) - await trie.put(Buffer.from('key3cc'), Buffer.from('aval3')) + await trie.put(utf8ToBytes('key1aa'), utf8ToBytes('0123456789012345678901234567890123456789xx')) + await trie.put(utf8ToBytes('key2bb'), utf8ToBytes('aval2')) + await trie.put(utf8ToBytes('key3cc'), utf8ToBytes('aval3')) - let proof = await trie.createProof(Buffer.from('key2bb')) - let val = await trie.verifyProof(trie.root(), Buffer.from('key2bb'), proof) - t.equal(val!.toString('utf8'), 'aval2') + let proof = await trie.createProof(utf8ToBytes('key2bb')) + let val = await trie.verifyProof(trie.root(), utf8ToBytes('key2bb'), proof) + t.equal(bytesToUtf8(val!), 'aval2') - proof = await trie.createProof(Buffer.from('key1aa')) - val = await trie.verifyProof(trie.root(), Buffer.from('key1aa'), proof) - t.equal(val!.toString('utf8'), '0123456789012345678901234567890123456789xx') + proof = await trie.createProof(utf8ToBytes('key1aa')) + val = await trie.verifyProof(trie.root(), utf8ToBytes('key1aa'), proof) + t.equal(bytesToUtf8(val!), '0123456789012345678901234567890123456789xx') - proof = await trie.createProof(Buffer.from('key2bb')) - val = await trie.verifyProof(trie.root(), Buffer.from('key2'), proof) + proof = await trie.createProof(utf8ToBytes('key2bb')) + val = await trie.verifyProof(trie.root(), utf8ToBytes('key2'), proof) // In this case, the proof _happens_ to contain enough nodes to prove `key2` because // traversing into `key22` would touch all the same nodes as traversing into `key2` t.equal(val, null, 'Expected value at a random key to be null') - let myKey = Buffer.from('anyrandomkey') + let myKey = utf8ToBytes('anyrandomkey') proof = await trie.createProof(myKey) val = await trie.verifyProof(trie.root(), myKey, proof) t.equal(val, null, 'Expected value to be null') - myKey = Buffer.from('anothergarbagekey') // should generate a valid proof of null + myKey = utf8ToBytes('anothergarbagekey') // should generate a valid proof of null proof = await trie.createProof(myKey) - proof.push(Buffer.from('123456')) // extra nodes are just ignored + proof.push(utf8ToBytes('123456')) // extra nodes are just ignored val = await trie.verifyProof(trie.root(), myKey, proof) t.equal(val, null, 'Expected value to be null') - await trie.put(Buffer.from('another'), Buffer.from('3498h4riuhgwe')) + await trie.put(utf8ToBytes('another'), utf8ToBytes('3498h4riuhgwe')) // to fail our proof we can request a proof for one key - proof = await trie.createProof(Buffer.from('another')) + proof = await trie.createProof(utf8ToBytes('another')) // and try to use that proof on another key try { - await trie.verifyProof(trie.root(), Buffer.from('key1aa'), proof) + await trie.verifyProof(trie.root(), utf8ToBytes('key1aa'), proof) t.fail('expected error: Invalid proof provided') } catch (e: any) { t.equal(e.message, 'Invalid proof provided') } // we can also corrupt a valid proof - proof = await trie.createProof(Buffer.from('key2bb')) + proof = await trie.createProof(utf8ToBytes('key2bb')) proof[0].reverse() try { - await trie.verifyProof(trie.root(), Buffer.from('key2bb'), proof) + await trie.verifyProof(trie.root(), utf8ToBytes('key2bb'), proof) t.fail('expected error: Invalid proof provided') } catch (e: any) { t.equal(e.message, 'Invalid proof provided') @@ -61,12 +62,12 @@ tape('simple merkle proofs generation and verification', function (tester) { // test an invalid exclusion proof by creating // a valid exclusion proof then making it non-null - myKey = Buffer.from('anyrandomkey') + myKey = utf8ToBytes('anyrandomkey') proof = await trie.createProof(myKey) val = await trie.verifyProof(trie.root(), myKey, proof) t.equal(val, null, 'Expected value to be null') // now make the key non-null so the exclusion proof becomes invalid - await trie.put(myKey, Buffer.from('thisisavalue')) + await trie.put(myKey, utf8ToBytes('thisisavalue')) try { await trie.verifyProof(trie.root(), myKey, proof) t.fail('expected error: Invalid proof provided') @@ -80,11 +81,11 @@ tape('simple merkle proofs generation and verification', function (tester) { it('create a merkle proof and verify it with a single long key', async (t) => { const trie = new Trie() - await trie.put(Buffer.from('key1aa'), Buffer.from('0123456789012345678901234567890123456789xx')) + await trie.put(utf8ToBytes('key1aa'), utf8ToBytes('0123456789012345678901234567890123456789xx')) - const proof = await trie.createProof(Buffer.from('key1aa')) - const val = await trie.verifyProof(trie.root(), Buffer.from('key1aa'), proof) - t.equal(val!.toString('utf8'), '0123456789012345678901234567890123456789xx') + const proof = await trie.createProof(utf8ToBytes('key1aa')) + const val = await trie.verifyProof(trie.root(), utf8ToBytes('key1aa'), proof) + t.equal(bytesToUtf8(val!), '0123456789012345678901234567890123456789xx') t.end() }) @@ -92,11 +93,11 @@ tape('simple merkle proofs generation and verification', function (tester) { it('create a merkle proof and verify it with a single short key', async (t) => { const trie = new Trie() - await trie.put(Buffer.from('key1aa'), Buffer.from('01234')) + await trie.put(utf8ToBytes('key1aa'), utf8ToBytes('01234')) - const proof = await trie.createProof(Buffer.from('key1aa')) - const val = await trie.verifyProof(trie.root(), Buffer.from('key1aa'), proof) - t.equal(val!.toString('utf8'), '01234') + const proof = await trie.createProof(utf8ToBytes('key1aa')) + const val = await trie.verifyProof(trie.root(), utf8ToBytes('key1aa'), proof) + t.equal(bytesToUtf8(val!), '01234') t.end() }) @@ -105,29 +106,29 @@ tape('simple merkle proofs generation and verification', function (tester) { const trie = new Trie() await trie.put( - Buffer.from('key1aa'), - Buffer.from('0123456789012345678901234567890123456789xxx') + utf8ToBytes('key1aa'), + utf8ToBytes('0123456789012345678901234567890123456789xxx') ) await trie.put( - Buffer.from('key1'), - Buffer.from('0123456789012345678901234567890123456789Very_Long') + utf8ToBytes('key1'), + utf8ToBytes('0123456789012345678901234567890123456789Very_Long') ) - await trie.put(Buffer.from('key2bb'), Buffer.from('aval3')) - await trie.put(Buffer.from('key2'), Buffer.from('short')) - await trie.put(Buffer.from('key3cc'), Buffer.from('aval3')) - await trie.put(Buffer.from('key3'), Buffer.from('1234567890123456789012345678901')) + await trie.put(utf8ToBytes('key2bb'), utf8ToBytes('aval3')) + await trie.put(utf8ToBytes('key2'), utf8ToBytes('short')) + await trie.put(utf8ToBytes('key3cc'), utf8ToBytes('aval3')) + await trie.put(utf8ToBytes('key3'), utf8ToBytes('1234567890123456789012345678901')) - let proof = await trie.createProof(Buffer.from('key1')) - let val = await trie.verifyProof(trie.root(), Buffer.from('key1'), proof) - t.equal(val!.toString('utf8'), '0123456789012345678901234567890123456789Very_Long') + let proof = await trie.createProof(utf8ToBytes('key1')) + let val = await trie.verifyProof(trie.root(), utf8ToBytes('key1'), proof) + t.equal(bytesToUtf8(val!), '0123456789012345678901234567890123456789Very_Long') - proof = await trie.createProof(Buffer.from('key2')) - val = await trie.verifyProof(trie.root(), Buffer.from('key2'), proof) - t.equal(val!.toString('utf8'), 'short') + proof = await trie.createProof(utf8ToBytes('key2')) + val = await trie.verifyProof(trie.root(), utf8ToBytes('key2'), proof) + t.equal(bytesToUtf8(val!), 'short') - proof = await trie.createProof(Buffer.from('key3')) - val = await trie.verifyProof(trie.root(), Buffer.from('key3'), proof) - t.equal(val!.toString('utf8'), '1234567890123456789012345678901') + proof = await trie.createProof(utf8ToBytes('key3')) + val = await trie.verifyProof(trie.root(), utf8ToBytes('key3'), proof) + t.equal(bytesToUtf8(val!), '1234567890123456789012345678901') t.end() }) @@ -135,21 +136,21 @@ tape('simple merkle proofs generation and verification', function (tester) { it('should succeed with a simple embedded extension-branch', async (t) => { const trie = new Trie() - await trie.put(Buffer.from('a'), Buffer.from('a')) - await trie.put(Buffer.from('b'), Buffer.from('b')) - await trie.put(Buffer.from('c'), Buffer.from('c')) + await trie.put(utf8ToBytes('a'), utf8ToBytes('a')) + await trie.put(utf8ToBytes('b'), utf8ToBytes('b')) + await trie.put(utf8ToBytes('c'), utf8ToBytes('c')) - let proof = await trie.createProof(Buffer.from('a')) - let val = await trie.verifyProof(trie.root(), Buffer.from('a'), proof) - t.equal(val!.toString('utf8'), 'a') + let proof = await trie.createProof(utf8ToBytes('a')) + let val = await trie.verifyProof(trie.root(), utf8ToBytes('a'), proof) + t.equal(bytesToUtf8(val!), 'a') - proof = await trie.createProof(Buffer.from('b')) - val = await trie.verifyProof(trie.root(), Buffer.from('b'), proof) - t.equal(val!.toString('utf8'), 'b') + proof = await trie.createProof(utf8ToBytes('b')) + val = await trie.verifyProof(trie.root(), utf8ToBytes('b'), proof) + t.equal(bytesToUtf8(val!), 'b') - proof = await trie.createProof(Buffer.from('c')) - val = await trie.verifyProof(trie.root(), Buffer.from('c'), proof) - t.equal(val!.toString('utf8'), 'c') + proof = await trie.createProof(utf8ToBytes('c')) + val = await trie.verifyProof(trie.root(), utf8ToBytes('c'), proof) + t.equal(bytesToUtf8(val!), 'c') t.end() }) diff --git a/packages/trie/test/proof/range.spec.ts b/packages/trie/test/proof/range.spec.ts index 214c55317a..f1c2118f63 100644 --- a/packages/trie/test/proof/range.spec.ts +++ b/packages/trie/test/proof/range.spec.ts @@ -1,4 +1,10 @@ -import { setLengthLeft, toBuffer } from '@ethereumjs/util' +import { + compareBytes, + concatBytes, + hexStringToBytes, + setLengthLeft, + toBytes, +} from '@ethereumjs/util' import * as crypto from 'crypto' import * as tape from 'tape' @@ -16,13 +22,13 @@ const TRIE_SIZE = 512 * @returns Trie object and sorted entries */ async function randomTrie(db: DB, addKey: boolean = true) { - const entries: [Buffer, Buffer][] = [] + const entries: [Uint8Array, Uint8Array][] = [] const trie = new Trie({ db }) if (addKey) { for (let i = 0; i < 100; i++) { - const key = setLengthLeft(toBuffer(i), 32) - const val = toBuffer(i) + const key = setLengthLeft(toBytes(i), 32) + const val = toBytes(i) await trie.put(key, val) entries.push([key, val]) } @@ -39,7 +45,7 @@ async function randomTrie(db: DB, addKey: boolean = true) { return { trie, - entries: entries.sort(([k1], [k2]) => k1.compare(k2)), + entries: entries.sort(([k1], [k2]) => compareBytes(k1, k2)), } } @@ -52,31 +58,31 @@ function getRandomIntInclusive(min: number, max: number): number { return Math.floor(Math.random() * (max - min + 1)) + min } -function decreaseKey(key: Buffer) { +function decreaseKey(key: Uint8Array) { for (let i = key.length - 1; i >= 0; i--) { if (key[i] > 0) { - return Buffer.concat([key.slice(0, i), toBuffer(key[i] - 1), key.slice(i + 1)]) + return concatBytes(key.slice(0, i), toBytes(key[i] - 1), key.slice(i + 1)) } } } -function increaseKey(key: Buffer) { +function increaseKey(key: Uint8Array) { for (let i = key.length - 1; i >= 0; i--) { if (key[i] < 255) { - return Buffer.concat([key.slice(0, i), toBuffer(key[i] + 1), key.slice(i + 1)]) + return concatBytes(key.slice(0, i), toBytes(key[i] + 1), key.slice(i + 1)) } } } async function verify( trie: Trie, - entries: [Buffer, Buffer][], + entries: [Uint8Array, Uint8Array][], start: number, end: number, - startKey?: Buffer, - endKey?: Buffer, - keys?: Buffer[], - vals?: Buffer[] + startKey?: Uint8Array, + endKey?: Uint8Array, + keys?: Uint8Array[], + vals?: Uint8Array[] ) { startKey = startKey ?? entries[start][0] endKey = endKey ?? entries[end][0] @@ -116,12 +122,18 @@ tape('simple merkle range proofs generation and verification', function (tester) const end = getRandomIntInclusive(start, entries.length - 1) const startKey = decreaseKey(entries[start][0]) - if (!startKey || (start > 0 && entries[start - 1][0].compare(startKey) >= 0)) { + if ( + startKey === undefined || + (start > 0 && compareBytes(entries[start - 1][0], startKey) >= 0) + ) { continue } const endKey = increaseKey(entries[end][0]) - if (!endKey || (end < entries.length - 1 && endKey.compare(entries[end + 1][0]) >= 0)) { + if ( + endKey === undefined || + (end < entries.length - 1 && compareBytes(endKey, entries[end + 1][0]) >= 0) + ) { continue } @@ -129,8 +141,8 @@ tape('simple merkle range proofs generation and verification', function (tester) } // Special case, two edge proofs for two edge key. - const startKey = Buffer.from('00'.repeat(32), 'hex') - const endKey = Buffer.from('ff'.repeat(32), 'hex') + const startKey = hexStringToBytes('00'.repeat(32)) + const endKey = hexStringToBytes('ff'.repeat(32)) t.equal(await verify(trie, entries, 0, entries.length - 1, startKey, endKey), false) t.end() @@ -187,10 +199,12 @@ tape('simple merkle range proofs generation and verification', function (tester) // Test the mini trie with only a single element. const tinyTrie = new Trie() - const tinyEntries: [Buffer, Buffer][] = [[crypto.randomBytes(32), crypto.randomBytes(20)]] + const tinyEntries: [Uint8Array, Uint8Array][] = [ + [crypto.randomBytes(32), crypto.randomBytes(20)], + ] await tinyTrie.put(tinyEntries[0][0], tinyEntries[0][1]) - const tinyStartKey = Buffer.from('00'.repeat(32), 'hex') + const tinyStartKey = hexStringToBytes('00'.repeat(32)) t.equal(await verify(tinyTrie, tinyEntries, 0, 0, tinyStartKey), false) }) @@ -219,15 +233,15 @@ tape('simple merkle range proofs generation and verification', function (tester) entries, 0, entries.length - 1, - Buffer.from('00'.repeat(32), 'hex'), - Buffer.from('ff'.repeat(32), 'hex') + hexStringToBytes('00'.repeat(32)), + hexStringToBytes('ff'.repeat(32)) ), false ) }) it('create a single side range proof and verify it', async (t) => { - const startKey = Buffer.from('00'.repeat(32), 'hex') + const startKey = hexStringToBytes('00'.repeat(32)) const { trie, entries } = await randomTrie(new MapDB(), false) const cases = [0, 1, 200, entries.length - 1] @@ -237,7 +251,7 @@ tape('simple merkle range proofs generation and verification', function (tester) }) it('create a revert single side range proof and verify it', async (t) => { - const endKey = Buffer.from('ff'.repeat(32), 'hex') + const endKey = hexStringToBytes('ff'.repeat(32)) const { trie, entries } = await randomTrie(new MapDB(), false) const cases = [0, 1, 200, entries.length - 1] @@ -247,7 +261,9 @@ tape('simple merkle range proofs generation and verification', function (tester) }) it('create a bad range proof and verify it', async (t) => { - const runTest = async (cb: (trie: Trie, entries: [Buffer, Buffer][]) => Promise) => { + const runTest = async ( + cb: (trie: Trie, entries: [Uint8Array, Uint8Array][]) => Promise + ) => { const { trie, entries } = await randomTrie(new MapDB(), false) let result = false @@ -306,17 +322,17 @@ tape('simple merkle range proofs generation and verification', function (tester) it('create a gapped range proof and verify it', async (t) => { const trie = new Trie() - const entries: [Buffer, Buffer][] = [] + const entries: [Uint8Array, Uint8Array][] = [] for (let i = 0; i < 10; i++) { - const key = setLengthLeft(toBuffer(i), 32) - const val = toBuffer(i) + const key = setLengthLeft(toBytes(i), 32) + const val = toBytes(i) await trie.put(key, val) entries.push([key, val]) } const start = 2 const end = 8 - const targetRange: [Buffer, Buffer][] = [] + const targetRange: [Uint8Array, Uint8Array][] = [] for (let i = start; i <= end; i++) { if (i === (start + end) / 2) { continue @@ -433,19 +449,19 @@ tape('simple merkle range proofs generation and verification', function (tester) // eslint-disable-next-line prefer-const for (let { start, end, expect } of cases) { - let startKey: Buffer - let endKey: Buffer + let startKey: Uint8Array + let endKey: Uint8Array if (start === -1) { start = 0 - startKey = Buffer.from('00'.repeat(32), 'hex') + startKey = hexStringToBytes('00'.repeat(32)) } else { startKey = entries[start][0] } if (end === -1) { end = entries.length - 1 - endKey = Buffer.from('ff'.repeat(32), 'hex') + endKey = hexStringToBytes('ff'.repeat(32)) } else { endKey = entries[end][0] } @@ -457,7 +473,7 @@ tape('simple merkle range proofs generation and verification', function (tester) it('create a bloated range proof and verify it', async (t) => { const { trie, entries } = await randomTrie(new MapDB(), false) - let bloatedProof: Buffer[] = [] + let bloatedProof: Uint8Array[] = [] for (let i = 0; i < TRIE_SIZE; i++) { bloatedProof = bloatedProof.concat(await trie.createProof(entries[i][0])) } diff --git a/packages/trie/test/stream.spec.ts b/packages/trie/test/stream.spec.ts index 54daf12f6a..c08606befa 100644 --- a/packages/trie/test/stream.spec.ts +++ b/packages/trie/test/stream.spec.ts @@ -1,3 +1,4 @@ +import { utf8ToBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' import { Trie } from '../src' @@ -10,87 +11,87 @@ tape('kv stream test', function (tester) { const ops = [ { type: 'del', - key: Buffer.from('father'), + key: utf8ToBytes('father'), }, { type: 'put', - key: Buffer.from('name'), - value: Buffer.from('Yuri Irsenovich Kim'), + key: utf8ToBytes('name'), + value: utf8ToBytes('Yuri Irsenovich Kim'), }, { type: 'put', - key: Buffer.from('dob'), - value: Buffer.from('16 February 1941'), + key: utf8ToBytes('dob'), + value: utf8ToBytes('16 February 1941'), }, { type: 'put', - key: Buffer.from('spouse'), - value: Buffer.from('Kim Young-sook'), + key: utf8ToBytes('spouse'), + value: utf8ToBytes('Kim Young-sook'), }, { type: 'put', - key: Buffer.from('occupation'), - value: Buffer.from('Clown'), + key: utf8ToBytes('occupation'), + value: utf8ToBytes('Clown'), }, { type: 'put', - key: Buffer.from('nameads'), - value: Buffer.from('Yuri Irsenovich Kim'), + key: utf8ToBytes('nameads'), + value: utf8ToBytes('Yuri Irsenovich Kim'), }, { type: 'put', - key: Buffer.from('namfde'), - value: Buffer.from('Yuri Irsenovich Kim'), + key: utf8ToBytes('namfde'), + value: utf8ToBytes('Yuri Irsenovich Kim'), }, { type: 'put', - key: Buffer.from('namsse'), - value: Buffer.from('Yuri Irsenovich Kim'), + key: utf8ToBytes('namsse'), + value: utf8ToBytes('Yuri Irsenovich Kim'), }, { type: 'put', - key: Buffer.from('dofab'), - value: Buffer.from('16 February 1941'), + key: utf8ToBytes('dofab'), + value: utf8ToBytes('16 February 1941'), }, { type: 'put', - key: Buffer.from('spoudse'), - value: Buffer.from('Kim Young-sook'), + key: utf8ToBytes('spoudse'), + value: utf8ToBytes('Kim Young-sook'), }, { type: 'put', - key: Buffer.from('occupdsation'), - value: Buffer.from('Clown'), + key: utf8ToBytes('occupdsation'), + value: utf8ToBytes('Clown'), }, { type: 'put', - key: Buffer.from('dozzzb'), - value: Buffer.from('16 February 1941'), + key: utf8ToBytes('dozzzb'), + value: utf8ToBytes('16 February 1941'), }, { type: 'put', - key: Buffer.from('spouszze'), - value: Buffer.from('Kim Young-sook'), + key: utf8ToBytes('spouszze'), + value: utf8ToBytes('Kim Young-sook'), }, { type: 'put', - key: Buffer.from('occupatdfion'), - value: Buffer.from('Clown'), + key: utf8ToBytes('occupatdfion'), + value: utf8ToBytes('Clown'), }, { type: 'put', - key: Buffer.from('dssob'), - value: Buffer.from('16 February 1941'), + key: utf8ToBytes('dssob'), + value: utf8ToBytes('16 February 1941'), }, { type: 'put', - key: Buffer.from('spossuse'), - value: Buffer.from('Kim Young-sook'), + key: utf8ToBytes('spossuse'), + value: utf8ToBytes('Kim Young-sook'), }, { type: 'put', - key: Buffer.from('occupssation'), - value: Buffer.from('Clown'), + key: utf8ToBytes('occupssation'), + value: utf8ToBytes('Clown'), }, ] as BatchDBOp[] @@ -128,33 +129,33 @@ tape('db stream test', function (tester) { const ops = [ { type: 'put', - key: Buffer.from('color'), - value: Buffer.from('purple'), + key: utf8ToBytes('color'), + value: utf8ToBytes('purple'), }, { type: 'put', - key: Buffer.from('food'), - value: Buffer.from('sushi'), + key: utf8ToBytes('food'), + value: utf8ToBytes('sushi'), }, { type: 'put', - key: Buffer.from('fight'), - value: Buffer.from('fire'), + key: utf8ToBytes('fight'), + value: utf8ToBytes('fire'), }, { type: 'put', - key: Buffer.from('colo'), - value: Buffer.from('trolo'), + key: utf8ToBytes('colo'), + value: utf8ToBytes('trolo'), }, { type: 'put', - key: Buffer.from('color'), - value: Buffer.from('blue'), + key: utf8ToBytes('color'), + value: utf8ToBytes('blue'), }, { type: 'put', - key: Buffer.from('color'), - value: Buffer.from('pink'), + key: utf8ToBytes('color'), + value: utf8ToBytes('pink'), }, ] as BatchDBOp[] diff --git a/packages/trie/test/trie/checkpoint.spec.ts b/packages/trie/test/trie/checkpoint.spec.ts index 87472caad0..ebd737adfe 100644 --- a/packages/trie/test/trie/checkpoint.spec.ts +++ b/packages/trie/test/trie/checkpoint.spec.ts @@ -1,3 +1,4 @@ +import { bytesToHex, bytesToUtf8, equalsBytes, utf8ToBytes } from '@ethereumjs/util' import { createHash } from 'crypto' import { keccak256 } from 'ethereum-cryptography/keccak' import * as tape from 'tape' @@ -16,17 +17,17 @@ tape('testing checkpoints', function (tester) { it('setup', async function (t) { trie = new Trie() - await trie.put(Buffer.from('do'), Buffer.from('verb')) - await trie.put(Buffer.from('doge'), Buffer.from('coin')) - preRoot = trie.root().toString('hex') + await trie.put(utf8ToBytes('do'), utf8ToBytes('verb')) + await trie.put(utf8ToBytes('doge'), utf8ToBytes('coin')) + preRoot = bytesToHex(trie.root()) t.end() }) it('should copy trie and get value added to original trie', async function (t) { trieCopy = trie.copy() - t.equal(trieCopy.root().toString('hex'), preRoot) - const res = await trieCopy.get(Buffer.from('do')) - t.ok(Buffer.from('verb').equals(Buffer.from(res!))) + t.equal(bytesToHex(trieCopy.root()), preRoot) + const res = await trieCopy.get(utf8ToBytes('do')) + t.ok(equalsBytes(utf8ToBytes('verb'), res!)) t.end() }) @@ -37,34 +38,34 @@ tape('testing checkpoints', function (tester) { }) it('should save to the cache', async function (t) { - await trie.put(Buffer.from('test'), Buffer.from('something')) - await trie.put(Buffer.from('love'), Buffer.from('emotion')) - postRoot = trie.root().toString('hex') + await trie.put(utf8ToBytes('test'), utf8ToBytes('something')) + await trie.put(utf8ToBytes('love'), utf8ToBytes('emotion')) + postRoot = bytesToHex(trie.root()) t.end() }) it('should get values from before checkpoint', async function (t) { - const res = await trie.get(Buffer.from('doge')) - t.ok(Buffer.from('coin').equals(Buffer.from(res!))) + const res = await trie.get(utf8ToBytes('doge')) + t.ok(equalsBytes(utf8ToBytes('coin'), res!)) t.end() }) it('should get values from cache', async function (t) { - const res = await trie.get(Buffer.from('love')) - t.ok(Buffer.from('emotion').equals(Buffer.from(res!))) + const res = await trie.get(utf8ToBytes('love')) + t.ok(equalsBytes(utf8ToBytes('emotion'), res!)) t.end() }) it('should copy trie and get upstream and cache values after checkpoint', async function (t) { trieCopy = trie.copy() - t.equal(trieCopy.root().toString('hex'), postRoot) + t.equal(bytesToHex(trieCopy.root()), postRoot) // @ts-expect-error t.equal(trieCopy._db.checkpoints.length, 1) t.ok(trieCopy.hasCheckpoints()) - const res = await trieCopy.get(Buffer.from('do')) - t.ok(Buffer.from('verb').equals(Buffer.from(res!))) - const res2 = await trieCopy.get(Buffer.from('love')) - t.ok(Buffer.from('emotion').equals(Buffer.from(res2!))) + const res = await trieCopy.get(utf8ToBytes('do')) + t.ok(equalsBytes(utf8ToBytes('verb'), res!)) + const res2 = await trieCopy.get(utf8ToBytes('love')) + t.ok(equalsBytes(utf8ToBytes('emotion'), res2!)) t.end() }) @@ -75,62 +76,62 @@ tape('testing checkpoints', function (tester) { useKeyHashingFunction: (value) => createHash('sha256').update(value).digest(), }) - await trie.put(Buffer.from('key1'), Buffer.from('value1')) + await trie.put(utf8ToBytes('key1'), utf8ToBytes('value1')) trie.checkpoint() - await trie.put(Buffer.from('key2'), Buffer.from('value2')) + await trie.put(utf8ToBytes('key2'), utf8ToBytes('value2')) const trieCopy = trie.copy() - const value = await trieCopy.get(Buffer.from('key1')) - t.equal(value!.toString(), 'value1') + const value = await trieCopy.get(utf8ToBytes('key1')) + t.equal(bytesToUtf8(value!), 'value1') t.end() }) it('should revert to the original root', async function (t) { t.ok(trie.hasCheckpoints()) await trie.revert() - t.equal(trie.root().toString('hex'), preRoot) + t.equal(bytesToHex(trie.root()), preRoot) t.notOk(trie.hasCheckpoints()) t.end() }) it('should not get values from cache after revert', async function (t) { - const res = await trie.get(Buffer.from('love')) + const res = await trie.get(utf8ToBytes('love')) t.notOk(res) t.end() }) it('should commit a checkpoint', async function (t) { trie.checkpoint() - await trie.put(Buffer.from('test'), Buffer.from('something')) - await trie.put(Buffer.from('love'), Buffer.from('emotion')) + await trie.put(utf8ToBytes('test'), utf8ToBytes('something')) + await trie.put(utf8ToBytes('love'), utf8ToBytes('emotion')) await trie.commit() t.equal(trie.hasCheckpoints(), false) - t.equal(trie.root().toString('hex'), postRoot) + t.equal(bytesToHex(trie.root()), postRoot) t.end() }) it('should get new values after commit', async function (t) { - const res = await trie.get(Buffer.from('love')) - t.ok(Buffer.from('emotion').equals(Buffer.from(res!))) + const res = await trie.get(utf8ToBytes('love')) + t.ok(equalsBytes(utf8ToBytes('emotion'), res!)) t.end() }) it('should commit a nested checkpoint', async function (t) { trie.checkpoint() - await trie.put(Buffer.from('test'), Buffer.from('something else')) + await trie.put(utf8ToBytes('test'), utf8ToBytes('something else')) const root = trie.root() trie.checkpoint() - await trie.put(Buffer.from('the feels'), Buffer.from('emotion')) + await trie.put(utf8ToBytes('the feels'), utf8ToBytes('emotion')) await trie.revert() await trie.commit() t.equal(trie.hasCheckpoints(), false) - t.equal(trie.root().toString('hex'), root.toString('hex')) + t.equal(trie.root(), root) t.end() }) - const k1 = Buffer.from('k1') - const v1 = Buffer.from('v1') - const v12 = Buffer.from('v12') - const v123 = Buffer.from('v123') + const k1 = utf8ToBytes('k1') + const v1 = utf8ToBytes('v1') + const v12 = utf8ToBytes('v12') + const v123 = utf8ToBytes('v123') it('revert -> put', async function (t) { trie = new Trie() @@ -213,8 +214,8 @@ tape('testing checkpoints', function (tester) { See PR 2203 and 2236. */ it('Checkpointing: nested checkpoints -> with pruning, verify that checkpoints are deep-copied', async (t) => { - const KEY = Buffer.from('last_block_height') - const KEY_ROOT = Buffer.from(keccak256(ROOT_DB_KEY)) + const KEY = utf8ToBytes('last_block_height') + const KEY_ROOT = keccak256(ROOT_DB_KEY) // Initialise State const CommittedState = await Trie.create({ @@ -224,7 +225,7 @@ tape('testing checkpoints', function (tester) { }) // Put some initial data - await CommittedState.put(KEY, Buffer.from('1')) + await CommittedState.put(KEY, utf8ToBytes('1')) // Take a checkpoint to enable nested checkpoints // From this point, CommittedState will not write on disk @@ -235,18 +236,18 @@ tape('testing checkpoints', function (tester) { MemoryState.checkpoint() // Test changes on MemoryState - await MemoryState.put(KEY, Buffer.from('2')) + await MemoryState.put(KEY, utf8ToBytes('2')) await MemoryState.commit() // The CommittedState should not change (not the key/value pairs, not the root, and not the root in DB) - t.equal((await CommittedState.get(KEY))?.toString(), '1') + t.equal(bytesToUtf8((await CommittedState.get(KEY))!), '1') t.equal( // @ts-expect-error - (await CommittedState._db.get(KEY_ROOT))?.toString('hex'), + bytesToHex(await CommittedState._db.get(KEY_ROOT)), '77ddd505d2a5b76a2a6ee34b827a0d35ca19f8d358bee3d74a84eab59794487c' ) t.equal( - CommittedState.root().toString('hex'), + bytesToHex(CommittedState.root()), '77ddd505d2a5b76a2a6ee34b827a0d35ca19f8d358bee3d74a84eab59794487c' ) @@ -269,13 +270,13 @@ tape('testing checkpoints', function (tester) { // I.e. the trie is pruned. t.deepEqual( // @ts-expect-error - [...CommittedState._db.db._database.values()].map((value) => value.toString('hex')), + [...CommittedState._db.db._database.values()].map((value) => bytesToHex(value)), [ 'd7eba6ee0f011acb031b79554d57001c42fbfabb150eb9fdd3b6d434f7b791eb', 'e3a1202418cf7414b1e6c2c8d92b4673eecdb4aac88f7f58623e3be903aefb2fd4655c32', ] ) // Verify that the key is updated - t.equal((await CommittedState.get(KEY))?.toString(), '2') + t.equal(bytesToUtf8((await CommittedState.get(KEY))!), '2') }) }) diff --git a/packages/trie/test/trie/prune.spec.ts b/packages/trie/test/trie/prune.spec.ts index f80bb17bda..d89950edad 100644 --- a/packages/trie/test/trie/prune.spec.ts +++ b/packages/trie/test/trie/prune.spec.ts @@ -1,49 +1,53 @@ -import { KECCAK256_RLP } from '@ethereumjs/util' +import { + KECCAK256_RLP, + equalsBytes, + hexStringToBytes, + randomBytes, + utf8ToBytes, +} from '@ethereumjs/util' import * as tape from 'tape' import { Trie } from '../../src' -const crypto = require('crypto') - tape('Pruned trie tests', function (tester) { const it = tester.test it('should default to not prune the trie', async function (st) { const trie = new Trie() - const key = Buffer.from('test') - await trie.put(key, Buffer.from('1')) - await trie.put(key, Buffer.from('2')) - await trie.put(key, Buffer.from('3')) - await trie.put(key, Buffer.from('4')) - await trie.put(key, Buffer.from('5')) - await trie.put(key, Buffer.from('6')) + const key = utf8ToBytes('test') + await trie.put(key, utf8ToBytes('1')) + await trie.put(key, utf8ToBytes('2')) + await trie.put(key, utf8ToBytes('3')) + await trie.put(key, utf8ToBytes('4')) + await trie.put(key, utf8ToBytes('5')) + await trie.put(key, utf8ToBytes('6')) st.equals((trie)._db.db._database.size, 6, 'DB size correct') }) it('should prune simple trie', async function (st) { const trie = new Trie({ useNodePruning: true }) - const key = Buffer.from('test') - await trie.put(key, Buffer.from('1')) - await trie.put(key, Buffer.from('2')) - await trie.put(key, Buffer.from('3')) - await trie.put(key, Buffer.from('4')) - await trie.put(key, Buffer.from('5')) - await trie.put(key, Buffer.from('6')) + const key = utf8ToBytes('test') + await trie.put(key, utf8ToBytes('1')) + await trie.put(key, utf8ToBytes('2')) + await trie.put(key, utf8ToBytes('3')) + await trie.put(key, utf8ToBytes('4')) + await trie.put(key, utf8ToBytes('5')) + await trie.put(key, utf8ToBytes('6')) st.equals((trie)._db.db._database.size, 1, 'DB size correct') }) it('should prune simple trie', async function (st) { const trie = new Trie({ useNodePruning: true }) - const key = Buffer.from('test') - await trie.put(key, Buffer.from('1')) + const key = utf8ToBytes('test') + await trie.put(key, utf8ToBytes('1')) st.equals((trie)._db.db._database.size, 1, 'DB size correct') await trie.del(key) st.equals((trie)._db.db._database.size, 0, 'DB size correct') - await trie.put(key, Buffer.from('1')) + await trie.put(key, utf8ToBytes('1')) st.equals((trie)._db.db._database.size, 1, 'DB size correct') }) @@ -54,7 +58,7 @@ tape('Pruned trie tests', function (tester) { const values = ['00', '02', '03', '04', '05'] for (let i = 0; i < keys.length; i++) { - await trie.put(Buffer.from(keys[i], 'hex'), Buffer.from(values[i], 'hex')) + await trie.put(hexStringToBytes(keys[i]), hexStringToBytes(values[i])) } st.end() @@ -62,25 +66,25 @@ tape('Pruned trie tests', function (tester) { it('should not prune if the same value is put twice', async function (st) { const trie = new Trie() - const key = Buffer.from('01') - const value = Buffer.from('02') + const key = utf8ToBytes('01') + const value = utf8ToBytes('02') await trie.put(key, value) await trie.put(key, value) const reported = await trie.get(key) - st.ok(reported?.equals(value), 'value matches expected value') + st.ok(equalsBytes(reported!, value), 'value matches expected value') }) it('should not throw if a key is either non-existent or deleted twice', async function (st) { const trie = new Trie() - const key = Buffer.from('01') - const value = Buffer.from('02') + const key = utf8ToBytes('01') + const value = utf8ToBytes('02') // key does not exist (empty trie) await trie.del(key) - const key2 = Buffer.from('AA') - const value2 = Buffer.from('ee') + const key2 = utf8ToBytes('AA') + const value2 = utf8ToBytes('ee') await trie.put(key2, value2) // key does not exist (non-empty trie) await trie.del(key) @@ -91,16 +95,17 @@ tape('Pruned trie tests', function (tester) { const reported = await trie.get(key) st.ok(reported === null, 'value is null') const reported2 = await trie.get(key2) - st.ok(reported2?.equals(value2), 'value matches expected value') + st.ok(equalsBytes(reported2!, value2), 'value matches expected value') }) it('should prune when keys are updated or deleted', async (st) => { for (let testID = 0; testID < 1; testID++) { const trie = new Trie({ useNodePruning: true }) - const keys: string[] = [] + const keys: Uint8Array[] = [] for (let i = 0; i < 100; i++) { - keys.push(crypto.randomBytes(32)) + keys.push(randomBytes(32)) } + const values: string[] = [] for (let i = 0; i < 1000; i++) { let val = Math.floor(Math.random() * 16384) @@ -113,7 +118,8 @@ tape('Pruned trie tests', function (tester) { for (let i = 0; i < keys.length; i++) { const idx = Math.floor(Math.random() * keys.length) const key = keys[idx] - await trie.put(Buffer.from(key), Buffer.from(values[i])) + + await trie.put(key, utf8ToBytes(values[i])) } st.ok(await trie.verifyPrunedIntegrity(), 'trie is correctly pruned') @@ -121,7 +127,7 @@ tape('Pruned trie tests', function (tester) { // Randomly delete keys for (let i = 0; i < 20; i++) { const idx = Math.floor(Math.random() * keys.length) - await trie.del(Buffer.from(keys[idx])) + await trie.del(keys[idx]) } st.ok(await trie.verifyPrunedIntegrity(), 'trie is correctly pruned') @@ -131,9 +137,9 @@ tape('Pruned trie tests', function (tester) { const idx = Math.floor(Math.random() * keys.length) const key = keys[idx] if (Math.random() < 0.5) { - await trie.put(Buffer.from(key), Buffer.from(values[i])) + await trie.put(key, utf8ToBytes(values[i])) } else { - await trie.del(Buffer.from(key)) + await trie.del(key) } } @@ -141,11 +147,11 @@ tape('Pruned trie tests', function (tester) { // Delete all keys for (let idx = 0; idx < 100; idx++) { - await trie.del(Buffer.from(keys[idx])) + await trie.del(keys[idx]) } st.ok(await trie.verifyPrunedIntegrity(), 'trie is correctly pruned') - st.ok(trie.root().equals(KECCAK256_RLP), 'trie is empty') + st.ok(equalsBytes(trie.root(), KECCAK256_RLP), 'trie is empty') let dbKeys = 0 for (const _dbkey of (trie)._db.db._database.keys()) { @@ -159,30 +165,30 @@ tape('Pruned trie tests', function (tester) { // Create empty Trie (is pruned) let trie = new Trie() // Create a new value (still is pruned) - await trie.put(Buffer.from('aa', 'hex'), Buffer.from('bb', 'hex')) + await trie.put(hexStringToBytes('aa'), hexStringToBytes('bb')) // Overwrite this value (trie is now not pruned anymore) - await trie.put(Buffer.from('aa', 'hex'), Buffer.from('aa', 'hex')) + await trie.put(hexStringToBytes('aa'), hexStringToBytes('aa')) st.ok(!(await trie.verifyPrunedIntegrity()), 'trie is not pruned') // Create new empty Trie (is pruned) trie = new Trie() // Create a new value raw in DB (is not pruned) - await (trie)._db.db.put(Buffer.from('aa', 'hex')) + await (trie)._db.db.put(utf8ToBytes('aa')) st.ok(!(await trie.verifyPrunedIntegrity()), 'trie is not pruned') - await (trie)._db.db.del(Buffer.from('aa', 'hex')) + await (trie)._db.db.del(utf8ToBytes('aa')) st.ok(await trie.verifyPrunedIntegrity(), 'trie is pruned') - await trie.put(Buffer.from('aa', 'hex'), Buffer.from('bb', 'hex')) + await trie.put(utf8ToBytes('aa'), utf8ToBytes('bb')) st.ok(await trie.verifyPrunedIntegrity(), 'trie is pruned') - await (trie)._db.db.put(Buffer.from('aa', 'hex')) + await (trie)._db.db.put(utf8ToBytes('aa')) st.ok(!(await trie.verifyPrunedIntegrity()), 'trie is not pruned') }) it('should prune when keys are updated or deleted (with `useRootPersistence` enabled)', async (st) => { for (let testID = 0; testID < 1; testID++) { const trie = await Trie.create({ useNodePruning: true, useRootPersistence: true }) - const keys: string[] = [] + const keys: Uint8Array[] = [] for (let i = 0; i < 100; i++) { - keys.push(crypto.randomBytes(32)) + keys.push(randomBytes(32)) } const values: string[] = [] for (let i = 0; i < 1000; i++) { @@ -196,7 +202,7 @@ tape('Pruned trie tests', function (tester) { for (let i = 0; i < keys.length; i++) { const idx = Math.floor(Math.random() * keys.length) const key = keys[idx] - await trie.put(Buffer.from(key), Buffer.from(values[i])) + await trie.put(key, utf8ToBytes(values[i])) } st.ok(await trie.verifyPrunedIntegrity(), 'trie is correctly pruned') @@ -204,7 +210,7 @@ tape('Pruned trie tests', function (tester) { // Randomly delete keys for (let i = 0; i < 20; i++) { const idx = Math.floor(Math.random() * keys.length) - await trie.del(Buffer.from(keys[idx])) + await trie.del(keys[idx]) } st.ok(await trie.verifyPrunedIntegrity(), 'trie is correctly pruned') @@ -214,9 +220,9 @@ tape('Pruned trie tests', function (tester) { const idx = Math.floor(Math.random() * keys.length) const key = keys[idx] if (Math.random() < 0.5) { - await trie.put(Buffer.from(key), Buffer.from(values[i])) + await trie.put(key, utf8ToBytes(values[i])) } else { - await trie.del(Buffer.from(key)) + await trie.del(key) } } @@ -224,11 +230,11 @@ tape('Pruned trie tests', function (tester) { // Delete all keys for (let idx = 0; idx < 100; idx++) { - await trie.del(Buffer.from(keys[idx])) + await trie.del(keys[idx]) } st.ok(await trie.verifyPrunedIntegrity(), 'trie is correctly pruned') - st.ok(trie.root().equals(KECCAK256_RLP), 'trie is empty') + st.ok(equalsBytes(trie.root(), KECCAK256_RLP), 'trie is empty') let dbKeys = 0 for (const _dbkey of (trie)._db.db._database.keys()) { diff --git a/packages/trie/test/trie/secure.spec.ts b/packages/trie/test/trie/secure.spec.ts index 1bd5ba52a5..30645e3fe2 100644 --- a/packages/trie/test/trie/secure.spec.ts +++ b/packages/trie/test/trie/secure.spec.ts @@ -1,3 +1,10 @@ +import { + bytesToPrefixedHexString, + bytesToUtf8, + equalsBytes, + hexStringToBytes, + utf8ToBytes, +} from '@ethereumjs/util' import { createHash } from 'crypto' import * as tape from 'tape' @@ -5,31 +12,31 @@ import { MapDB, ROOT_DB_KEY, Trie } from '../../src' tape('SecureTrie', function (t) { const trie = new Trie({ useKeyHashing: true, db: new MapDB() }) - const k = Buffer.from('foo') - const v = Buffer.from('bar') + const k = utf8ToBytes('foo') + const v = utf8ToBytes('bar') t.test('put and get value', async function (st) { await trie.put(k, v) const res = await trie.get(k) - st.ok(v.equals(res!)) + st.ok(equalsBytes(v, res!)) st.end() }) t.test('copy trie', async function (st) { const t = trie.copy() const res = await t.get(k) - st.ok(v.equals(res!)) + st.ok(equalsBytes(v, res!)) st.end() }) tape('SecureTrie proof', function (t) { t.test('create a merkle proof and verify it with a single short key', async function (st) { const trie = new Trie({ useKeyHashing: true, db: new MapDB() }) - await trie.put(Buffer.from('key1aa'), Buffer.from('01234')) + await trie.put(utf8ToBytes('key1aa'), utf8ToBytes('01234')) - const proof = await trie.createProof(Buffer.from('key1aa')) - const val = await trie.verifyProof(trie.root(), Buffer.from('key1aa'), proof) - st.equal(val!.toString('utf8'), '01234') + const proof = await trie.createProof(utf8ToBytes('key1aa')) + const val = await trie.verifyProof(trie.root(), utf8ToBytes('key1aa'), proof) + st.equal(bytesToUtf8(val!), '01234') st.end() }) }) @@ -42,11 +49,11 @@ tape('SecureTrie', function (t) { for (const row of jsonTests.emptyValues.in) { const val = row[1] !== undefined && row[1] !== null - ? Buffer.from(row[1]) - : (null as unknown as Buffer) - await trie.put(Buffer.from(row[0]), val) + ? utf8ToBytes(row[1]) + : (null as unknown as Uint8Array) + await trie.put(utf8ToBytes(row[0]), val) } - t.equal('0x' + trie.root().toString('hex'), jsonTests.emptyValues.root) + t.equal(bytesToPrefixedHexString(trie.root()), jsonTests.emptyValues.root) t.end() }) @@ -55,11 +62,11 @@ tape('SecureTrie', function (t) { for (const row of jsonTests.branchingTests.in) { const val = row[1] !== undefined && row[1] !== null - ? Buffer.from(row[1]) - : (null as unknown as Buffer) - await trie.put(Buffer.from(row[0]), val) + ? utf8ToBytes(row[1]) + : (null as unknown as Uint8Array) + await trie.put(utf8ToBytes(row[0]), val) } - t.equal('0x' + trie.root().toString('hex'), jsonTests.branchingTests.root) + t.equal(bytesToPrefixedHexString(trie.root()), jsonTests.branchingTests.root) t.end() }) @@ -67,11 +74,11 @@ tape('SecureTrie', function (t) { for (const row of jsonTests.jeff.in) { let val = row[1] if (val !== undefined && val !== null) { - val = Buffer.from(row[1].slice(2), 'hex') + val = hexStringToBytes(row[1].slice(2)) } - await trie.put(Buffer.from(row[0].slice(2), 'hex'), val) + await trie.put(hexStringToBytes(row[0].slice(2)), val) } - t.equal('0x' + trie.root().toString('hex'), jsonTests.jeff.root.toString('hex')) + t.equal(bytesToPrefixedHexString(trie.root()), jsonTests.jeff.root) t.end() }) @@ -79,7 +86,7 @@ tape('SecureTrie', function (t) { const trie = new Trie({ useKeyHashing: true, db: new MapDB(), useRootPersistence: true }) try { - await trie.put(ROOT_DB_KEY, Buffer.from('bar')) + await trie.put(ROOT_DB_KEY, utf8ToBytes('bar')) st.fail("Attempting to set '__root__' should fail but it did not.") } catch ({ message }) { @@ -90,45 +97,38 @@ tape('SecureTrie', function (t) { }) const trie = new Trie({ useKeyHashing: true, db: new MapDB() }) -const a = Buffer.from( - 'f8448080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0a155280bc3c09fd31b0adebbdd4ef3d5128172c0d2008be964dc9e10e0f0fedf', - 'hex' +const a = hexStringToBytes( + 'f8448080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0a155280bc3c09fd31b0adebbdd4ef3d5128172c0d2008be964dc9e10e0f0fedf' ) -const ak = Buffer.from('095e7baea6a6c7c4c2dfeb977efac326af552d87', 'hex') -const b = Buffer.from( - 'f844802ea056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0db94dc4aab9b6a1a11956906ea34f3252f394576aece12199b23b269bb2738ab', - 'hex' +const ak = hexStringToBytes('095e7baea6a6c7c4c2dfeb977efac326af552d87') +const b = hexStringToBytes( + 'f844802ea056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0db94dc4aab9b6a1a11956906ea34f3252f394576aece12199b23b269bb2738ab' ) -const bk = Buffer.from('945304eb96065b2a98b57a48a06ae28d285a71b5', 'hex') -const c = Buffer.from( - 'f84c80880de0b6b3a7640000a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470', - 'hex' +const bk = hexStringToBytes('945304eb96065b2a98b57a48a06ae28d285a71b5') +const c = hexStringToBytes( + 'f84c80880de0b6b3a7640000a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470' ) -const ck = Buffer.from('a94f5374fce5edbc8e2a8697c15331677e6ebf0b', 'hex') +const ck = hexStringToBytes('a94f5374fce5edbc8e2a8697c15331677e6ebf0b') // checkpoint // checkpoint // commit -const d = Buffer.from( - 'f8488084535500b1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0a155280bc3c09fd31b0adebbdd4ef3d5128172c0d2008be964dc9e10e0f0fedf', - 'hex' +const d = hexStringToBytes( + 'f8488084535500b1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0a155280bc3c09fd31b0adebbdd4ef3d5128172c0d2008be964dc9e10e0f0fedf' ) -const dk = Buffer.from('095e7baea6a6c7c4c2dfeb977efac326af552d87', 'hex') -const e = Buffer.from( - 'f8478083010851a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0db94dc4aab9b6a1a11956906ea34f3252f394576aece12199b23b269bb2738ab', - 'hex' +const dk = hexStringToBytes('095e7baea6a6c7c4c2dfeb977efac326af552d87') +const e = hexStringToBytes( + 'f8478083010851a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0db94dc4aab9b6a1a11956906ea34f3252f394576aece12199b23b269bb2738ab' ) -const ek = Buffer.from('945304eb96065b2a98b57a48a06ae28d285a71b5', 'hex') -const f = Buffer.from( - 'f84c01880de0b6b3540df72ca056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470', - 'hex' +const ek = hexStringToBytes('945304eb96065b2a98b57a48a06ae28d285a71b5') +const f = hexStringToBytes( + 'f84c01880de0b6b3540df72ca056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470' ) -const fk = Buffer.from('a94f5374fce5edbc8e2a8697c15331677e6ebf0b', 'hex') +const fk = hexStringToBytes('a94f5374fce5edbc8e2a8697c15331677e6ebf0b') // commit -const g = Buffer.from( - 'f8488084535500b1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0a155280bc3c09fd31b0adebbdd4ef3d5128172c0d2008be964dc9e10e0f0fedf', - 'hex' +const g = hexStringToBytes( + 'f8488084535500b1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0a155280bc3c09fd31b0adebbdd4ef3d5128172c0d2008be964dc9e10e0f0fedf' ) -const gk = Buffer.from('095e7baea6a6c7c4c2dfeb977efac326af552d87', 'hex') +const gk = hexStringToBytes('095e7baea6a6c7c4c2dfeb977efac326af552d87') tape('secure tests should not crash', async function (t) { await trie.put(ak, a) @@ -149,24 +149,24 @@ tape('SecureTrie.copy', function (it) { it.test('created copy includes values added after checkpoint', async function (t) { const trie = new Trie({ useKeyHashing: true, db: new MapDB() }) - await trie.put(Buffer.from('key1'), Buffer.from('value1')) + await trie.put(utf8ToBytes('key1'), utf8ToBytes('value1')) trie.checkpoint() - await trie.put(Buffer.from('key2'), Buffer.from('value2')) + await trie.put(utf8ToBytes('key2'), utf8ToBytes('value2')) const trieCopy = trie.copy() - const value = await trieCopy.get(Buffer.from('key2')) - t.equal(value!.toString(), 'value2') + const value = await trieCopy.get(utf8ToBytes('key2')) + t.equal(bytesToUtf8(value!), 'value2') t.end() }) it.test('created copy includes values added before checkpoint', async function (t) { const trie = new Trie({ useKeyHashing: true, db: new MapDB() }) - await trie.put(Buffer.from('key1'), Buffer.from('value1')) + await trie.put(utf8ToBytes('key1'), utf8ToBytes('value1')) trie.checkpoint() - await trie.put(Buffer.from('key2'), Buffer.from('value2')) + await trie.put(utf8ToBytes('key2'), utf8ToBytes('value2')) const trieCopy = trie.copy() - const value = await trieCopy.get(Buffer.from('key1')) - t.equal(value!.toString(), 'value1') + const value = await trieCopy.get(utf8ToBytes('key1')) + t.equal(bytesToUtf8(value!), 'value1') t.end() }) @@ -177,12 +177,12 @@ tape('SecureTrie.copy', function (it) { useKeyHashingFunction: (value) => createHash('sha256').update(value).digest(), }) - await trie.put(Buffer.from('key1'), Buffer.from('value1')) + await trie.put(utf8ToBytes('key1'), utf8ToBytes('value1')) trie.checkpoint() - await trie.put(Buffer.from('key2'), Buffer.from('value2')) + await trie.put(utf8ToBytes('key2'), utf8ToBytes('value2')) const trieCopy = trie.copy() - const value = await trieCopy.get(Buffer.from('key1')) - t.equal(value!.toString(), 'value1') + const value = await trieCopy.get(utf8ToBytes('key1')) + t.equal(bytesToUtf8(value!), 'value1') t.end() }) }) diff --git a/packages/trie/test/trie/trie.spec.ts b/packages/trie/test/trie/trie.spec.ts index 564530a99c..8ffcf94607 100644 --- a/packages/trie/test/trie/trie.spec.ts +++ b/packages/trie/test/trie/trie.spec.ts @@ -1,13 +1,9 @@ -import { KECCAK256_RLP } from '@ethereumjs/util' +import { KECCAK256_RLP, bytesToHex, equalsBytes, utf8ToBytes } from '@ethereumjs/util' import { keccak256 } from 'ethereum-cryptography/keccak' import * as tape from 'tape' import { ROOT_DB_KEY as BASE_DB_KEY, MapDB, Trie } from '../../src' -function bytesToHex(bytes: Buffer | null) { - return bytes?.toString('hex') -} - for (const { constructor, defaults, title } of [ { constructor: Trie, @@ -23,9 +19,9 @@ for (const { constructor, defaults, title } of [ ]) { const IS_SECURE_TRIE = title === 'SecureTrie' - let ROOT_DB_KEY: Buffer + let ROOT_DB_KEY: Uint8Array if (IS_SECURE_TRIE) { - ROOT_DB_KEY = Buffer.from(keccak256(BASE_DB_KEY)) + ROOT_DB_KEY = keccak256(BASE_DB_KEY) } else { ROOT_DB_KEY = BASE_DB_KEY } @@ -104,7 +100,7 @@ for (const { constructor, defaults, title } of [ // @ts-expect-error st.equal(await trie._db.get(ROOT_DB_KEY), null) - await trie.put(Buffer.from('foo'), Buffer.from('bar')) + await trie.put(utf8ToBytes('foo'), utf8ToBytes('bar')) // @ts-expect-error st.equal(bytesToHex(await trie._db.get(ROOT_DB_KEY)), EXPECTED_ROOTS) @@ -121,12 +117,12 @@ for (const { constructor, defaults, title } of [ }) // @ts-expect-error - st.true((await trie._db.get(ROOT_DB_KEY))?.equals(KECCAK256_RLP)) + st.ok(equalsBytes((await trie._db.get(ROOT_DB_KEY))!, KECCAK256_RLP)) - await trie.put(Buffer.from('foo'), Buffer.from('bar')) + await trie.put(utf8ToBytes('foo'), utf8ToBytes('bar')) // @ts-expect-error - st.false((await trie._db.get(ROOT_DB_KEY))?.equals(KECCAK256_RLP)) + st.false(equalsBytes((await trie._db.get(ROOT_DB_KEY))!, KECCAK256_RLP)) st.end() }) @@ -143,7 +139,7 @@ for (const { constructor, defaults, title } of [ // @ts-expect-error st.equal(await trie._db.get(ROOT_DB_KEY), null) - await trie.put(Buffer.from('do_not_persist_with_db'), Buffer.from('bar')) + await trie.put(utf8ToBytes('do_not_persist_with_db'), utf8ToBytes('bar')) // @ts-expect-error st.equal(await trie._db.get(ROOT_DB_KEY), null) @@ -158,7 +154,7 @@ for (const { constructor, defaults, title } of [ // @ts-expect-error st.equal(await trie._db.get(ROOT_DB_KEY), null) - await trie.put(Buffer.from('do_not_persist_without_db'), Buffer.from('bar')) + await trie.put(utf8ToBytes('do_not_persist_without_db'), utf8ToBytes('bar')) // @ts-expect-error st.notEqual(await trie._db.get(ROOT_DB_KEY), null) @@ -172,7 +168,7 @@ for (const { constructor, defaults, title } of [ const trie = await constructor.create({ ...defaults, db, useRootPersistence: true }) // @ts-expect-error st.equal(await trie._db.get(ROOT_DB_KEY), null) - await trie.put(Buffer.from('foo'), Buffer.from('bar')) + await trie.put(utf8ToBytes('foo'), utf8ToBytes('bar')) // @ts-expect-error st.equal(bytesToHex(await trie._db.get(ROOT_DB_KEY)), EXPECTED_ROOTS) @@ -197,7 +193,7 @@ for (const { constructor, defaults, title } of [ const trie = new constructor({ ...defaults, db: new MapDB(), useRootPersistence: true }) try { - await trie.put(BASE_DB_KEY, Buffer.from('bar')) + await trie.put(BASE_DB_KEY, utf8ToBytes('bar')) st.fail("Attempting to set '__root__' should fail but it did not.") } catch ({ message }) { st.equal(message, "Attempted to set '__root__' key but it is not allowed.") diff --git a/packages/tx/examples/custom-chain-tx.ts b/packages/tx/examples/custom-chain-tx.ts index 1e60047058..ecb8cf6017 100644 --- a/packages/tx/examples/custom-chain-tx.ts +++ b/packages/tx/examples/custom-chain-tx.ts @@ -1,6 +1,7 @@ import { Address } from '@ethereumjs/util' import { Common } from '@ethereumjs/common' import { Transaction } from '../src' +import { hexToBytes } from 'ethereum-cryptography/utils' // In this example we create a transaction for a custom network. @@ -34,10 +35,7 @@ const tx = Transaction.fromTxData( // Once we created the transaction using the custom Common object, we can use it as a normal tx. // Here we sign it and validate its signature -const privateKey = Buffer.from( - 'e331b6d69882b4cb4ea581d88e0b604039a3de5967688d3dcffdd2270c0fd109', - 'hex' -) +const privateKey = hexToBytes('e331b6d69882b4cb4ea581d88e0b604039a3de5967688d3dcffdd2270c0fd109') const signedTx = tx.sign(privateKey) const address = Address.fromPrivateKey(privateKey) diff --git a/packages/tx/examples/ropsten-tx.ts b/packages/tx/examples/ropsten-tx.ts index 0b1f50c823..4f4803dc77 100644 --- a/packages/tx/examples/ropsten-tx.ts +++ b/packages/tx/examples/ropsten-tx.ts @@ -1,8 +1,8 @@ import { Transaction } from '../src' -import { toBuffer } from '@ethereumjs/util' +import { toBytes } from '@ethereumjs/util' import { Chain, Common, Hardfork } from '@ethereumjs/common' -const txData = toBuffer( +const txData = toBytes( '0xf9010b82930284d09dc30083419ce0942d18de92e0f9aee1a29770c3b15c6cf8ac5498e580b8a42f43f4fb0000000000000000000000000000000000000000000000000000016b78998da900000000000000000000000000000000000000000000000000000000000cb1b70000000000000000000000000000000000000000000000000000000000000fa00000000000000000000000000000000000000000000000000000000001363e4f00000000000000000000000000000000000000000000000000000000000186a029a0fac36e66d329af0e831b2e61179b3ec8d7c7a8a2179e303cfed3364aff2bc3e4a07cb73d56e561ccbd838818dd3dea5fa0b5158577ffc61c0e6ec1f0ed55716891' ) diff --git a/packages/tx/examples/transactions.ts b/packages/tx/examples/transactions.ts index dc3a8dc1c9..67a00c554f 100644 --- a/packages/tx/examples/transactions.ts +++ b/packages/tx/examples/transactions.ts @@ -3,7 +3,8 @@ // Install the dependencies and run `npx ts-node examples/transactions.ts` import { Transaction } from '../src' -import { toBuffer } from '@ethereumjs/util' +import { bytesToPrefixedHexString, toBytes } from '@ethereumjs/util' +import { hexToBytes } from 'ethereum-cryptography/utils' // We create an unsigned transaction. // Notice we don't set the `to` field because we are creating a new contract. @@ -17,10 +18,7 @@ const tx = Transaction.fromTxData({ }) // We sign the transaction with this private key. -const privateKey = Buffer.from( - 'e331b6d69882b4cb4ea581d88e0b604039a3de5967688d3dcffdd2270c0fd109', - 'hex' -) +const privateKey = hexToBytes('e331b6d69882b4cb4ea581d88e0b604039a3de5967688d3dcffdd2270c0fd109') const signedTx = tx.sign(privateKey) @@ -33,7 +31,7 @@ console.log('Total Amount of wei needed:' + feeCost.toString()) // Lets serialize the transaction console.log('---Serialized TX----') -console.log(signedTx.serialize().toString('hex')) +console.log(bytesToPrefixedHexString(signedTx.serialize())) console.log('--------------------') // Parsing & Validating Transactions @@ -53,7 +51,7 @@ const rawTx = [ '0x5bd428537f05f9830e93792f90ea6a3e2d1ee84952dd96edbae9f658f831ab13', ] -const tx2 = Transaction.fromValuesArray(rawTx.map(toBuffer)) // This is also a mainnet transaction +const tx2 = Transaction.fromValuesArray(rawTx.map(toBytes)) // This is also a mainnet transaction // So assuming that you were able to parse the transaction, we will now get the sender's address. diff --git a/packages/tx/src/baseTransaction.ts b/packages/tx/src/baseTransaction.ts index beaa778d1d..fa470039d0 100644 --- a/packages/tx/src/baseTransaction.ts +++ b/packages/tx/src/baseTransaction.ts @@ -4,12 +4,12 @@ import { MAX_INTEGER, MAX_UINT64, SECP256K1_ORDER_DIV_2, - bufferToBigInt, - bufferToHex, + bytesToBigInt, + bytesToHex, ecsign, publicToAddress, - toBuffer, - unpadBuffer, + toBytes, + unpadBytes, } from '@ethereumjs/util' import { Capability } from './types' @@ -28,7 +28,7 @@ import type { import type { BigIntLike } from '@ethereumjs/util' interface TransactionCache { - hash: Buffer | undefined + hash: Uint8Array | undefined dataFee?: { value: bigint hardfork: string | Hardfork @@ -49,7 +49,7 @@ export abstract class BaseTransaction { public readonly gasLimit: bigint public readonly to?: Address public readonly value: bigint - public readonly data: Buffer + public readonly data: Uint8Array public readonly v?: bigint public readonly r?: bigint @@ -91,24 +91,24 @@ export abstract class BaseTransaction { constructor(txData: TxData | AccessListEIP2930TxData | FeeMarketEIP1559TxData, opts: TxOptions) { const { nonce, gasLimit, to, value, data, v, r, s, type } = txData - this._type = Number(bufferToBigInt(toBuffer(type))) + this._type = Number(bytesToBigInt(toBytes(type))) this.txOptions = opts - const toB = toBuffer(to === '' ? '0x' : to) - const vB = toBuffer(v === '' ? '0x' : v) - const rB = toBuffer(r === '' ? '0x' : r) - const sB = toBuffer(s === '' ? '0x' : s) + const toB = toBytes(to === '' ? '0x' : to) + const vB = toBytes(v === '' ? '0x' : v) + const rB = toBytes(r === '' ? '0x' : r) + const sB = toBytes(s === '' ? '0x' : s) - this.nonce = bufferToBigInt(toBuffer(nonce === '' ? '0x' : nonce)) - this.gasLimit = bufferToBigInt(toBuffer(gasLimit === '' ? '0x' : gasLimit)) + this.nonce = bytesToBigInt(toBytes(nonce === '' ? '0x' : nonce)) + this.gasLimit = bytesToBigInt(toBytes(gasLimit === '' ? '0x' : gasLimit)) this.to = toB.length > 0 ? new Address(toB) : undefined - this.value = bufferToBigInt(toBuffer(value === '' ? '0x' : value)) - this.data = toBuffer(data === '' ? '0x' : data) + this.value = bytesToBigInt(toBytes(value === '' ? '0x' : value)) + this.data = toBytes(data === '' ? '0x' : data) - this.v = vB.length > 0 ? bufferToBigInt(vB) : undefined - this.r = rB.length > 0 ? bufferToBigInt(rB) : undefined - this.s = sB.length > 0 ? bufferToBigInt(sB) : undefined + this.v = vB.length > 0 ? bytesToBigInt(vB) : undefined + this.r = rB.length > 0 ? bytesToBigInt(rB) : undefined + this.s = sB.length > 0 ? bytesToBigInt(sB) : undefined this._validateCannotExceedMaxInteger({ value: this.value, r: this.r, s: this.s }) @@ -242,16 +242,16 @@ export abstract class BaseTransaction { * If the tx's `to` is to the creation address */ toCreationAddress(): boolean { - return this.to === undefined || this.to.buf.length === 0 + return this.to === undefined || this.to.bytes.length === 0 } /** - * Returns a Buffer Array of the raw Buffers of this transaction, in order. + * Returns a Uint8Array Array of the raw Bytes of this transaction, in order. * * Use {@link BaseTransaction.serialize} to add a transaction to a block * with {@link Block.fromValuesArray}. * - * For an unsigned tx this method uses the empty Buffer values for the + * For an unsigned tx this method uses the empty Bytes values for the * signature parameters `v`, `r` and `s` for encoding. For an EIP-155 compliant * representation for external signing use {@link BaseTransaction.getMessageToSign}. */ @@ -260,18 +260,18 @@ export abstract class BaseTransaction { /** * Returns the encoding of the transaction. */ - abstract serialize(): Buffer + abstract serialize(): Uint8Array // Returns the unsigned tx (hashed or raw), which is used to sign the transaction. // // Note: do not use code docs here since VS Studio is then not able to detect the // comments from the inherited methods - abstract getMessageToSign(hashMessage: false): Buffer | Buffer[] - abstract getMessageToSign(hashMessage?: true): Buffer + abstract getMessageToSign(hashMessage: false): Uint8Array | Uint8Array[] + abstract getMessageToSign(hashMessage?: true): Uint8Array - abstract hash(): Buffer + abstract hash(): Uint8Array - abstract getMessageToVerifySignature(): Buffer + abstract getMessageToVerifySignature(): Uint8Array public isSigned(): boolean { const { v, r, s } = this @@ -289,7 +289,7 @@ export abstract class BaseTransaction { try { // Main signature verification is done in `getSenderPublicKey()` const publicKey = this.getSenderPublicKey() - return unpadBuffer(publicKey).length !== 0 + return unpadBytes(publicKey).length !== 0 } catch (e: any) { return false } @@ -305,7 +305,7 @@ export abstract class BaseTransaction { /** * Returns the public key of the sender */ - abstract getSenderPublicKey(): Buffer + abstract getSenderPublicKey(): Uint8Array /** * Signs a transaction. @@ -316,7 +316,7 @@ export abstract class BaseTransaction { * const signedTx = tx.sign(privateKey) * ``` */ - sign(privateKey: Buffer): TransactionObject { + sign(privateKey: Uint8Array): TransactionObject { if (privateKey.length !== 32) { const msg = this._errorMsg('Private key must be 32 bytes in length.') throw new Error(msg) @@ -357,7 +357,7 @@ export abstract class BaseTransaction { abstract toJSON(): JsonTx // Accept the v,r,s values from the `sign` method, and convert this into a TransactionObject - protected abstract _processSignature(v: bigint, r: Buffer, s: Buffer): TransactionObject + protected abstract _processSignature(v: bigint, r: Uint8Array, s: Uint8Array): TransactionObject /** * Does chain ID checks on common and returns a common @@ -370,7 +370,7 @@ export abstract class BaseTransaction { protected _getCommon(common?: Common, chainId?: BigIntLike) { // Chain ID provided if (chainId !== undefined) { - const chainIdBigInt = bufferToBigInt(toBuffer(chainId)) + const chainIdBigInt = bytesToBigInt(toBytes(chainId)) if (common) { if (common.chainId() !== chainIdBigInt) { const msg = this._errorMsg('The chain ID does not match the chain ID of Common') @@ -504,7 +504,7 @@ export abstract class BaseTransaction { protected _getSharedErrorPostfix() { let hash = '' try { - hash = this.isSigned() ? bufferToHex(this.hash()) : 'not available (unsigned)' + hash = this.isSigned() ? bytesToHex(this.hash()) : 'not available (unsigned)' } catch (e: any) { hash = 'error' } diff --git a/packages/tx/src/eip1559Transaction.ts b/packages/tx/src/eip1559Transaction.ts index a1532f6f0b..a98af66b00 100644 --- a/packages/tx/src/eip1559Transaction.ts +++ b/packages/tx/src/eip1559Transaction.ts @@ -1,13 +1,16 @@ import { RLP } from '@ethereumjs/rlp' import { MAX_INTEGER, - arrToBufArr, bigIntToHex, - bigIntToUnpaddedBuffer, - bufArrToArr, - bufferToBigInt, + bigIntToUnpaddedBytes, + bytesToBigInt, + bytesToHex, + bytesToPrefixedHexString, + concatBytes, ecrecover, - toBuffer, + equalsBytes, + hexStringToBytes, + toBytes, validateNoLeadingZeroes, } from '@ethereumjs/util' import { keccak256 } from 'ethereum-cryptography/keccak' @@ -17,7 +20,7 @@ import { AccessLists } from './util' import type { AccessList, - AccessListBuffer, + AccessListBytes, FeeMarketEIP1559TxData, FeeMarketEIP1559ValuesArray, JsonTx, @@ -26,7 +29,7 @@ import type { import type { Common } from '@ethereumjs/common' const TRANSACTION_TYPE = 2 -const TRANSACTION_TYPE_BUFFER = Buffer.from(TRANSACTION_TYPE.toString(16).padStart(2, '0'), 'hex') +const TRANSACTION_TYPE_BYTES = hexStringToBytes(TRANSACTION_TYPE.toString(16).padStart(2, '0')) /** * Typed transaction with a new gas fee market mechanism @@ -36,7 +39,7 @@ const TRANSACTION_TYPE_BUFFER = Buffer.from(TRANSACTION_TYPE.toString(16).padSta */ export class FeeMarketEIP1559Transaction extends BaseTransaction { public readonly chainId: bigint - public readonly accessList: AccessListBuffer + public readonly accessList: AccessListBytes public readonly AccessListJSON: AccessList public readonly maxPriorityFeePerGas: bigint public readonly maxFeePerGas: bigint @@ -71,16 +74,16 @@ export class FeeMarketEIP1559Transaction extends BaseTransaction { public readonly chainId: bigint - public readonly accessList: AccessListBuffer + public readonly accessList: AccessListBytes public readonly AccessListJSON: AccessList public readonly gasPrice: bigint @@ -70,22 +73,25 @@ export class AccessListEIP2930Transaction extends BaseTransaction { public readonly chainId: bigint - public readonly accessList: AccessListBuffer + public readonly accessList: AccessListBytes public readonly AccessListJSON: AccessList public readonly maxPriorityFeePerGas: bigint public readonly maxFeePerGas: bigint public readonly maxFeePerDataGas: bigint public readonly common: Common - public versionedHashes: Buffer[] - blobs?: Buffer[] // This property should only be populated when the transaction is in the "Network Wrapper" format - kzgCommitments?: Buffer[] // This property should only be populated when the transaction is in the "Network Wrapper" format - aggregateKzgProof?: Buffer // This property should only be populated when the transaction is in the "Network Wrapper" format + public versionedHashes: Uint8Array[] + blobs?: Uint8Array[] // This property should only be populated when the transaction is in the "Network Wrapper" format + kzgCommitments?: Uint8Array[] // This property should only be populated when the transaction is in the "Network Wrapper" format + aggregateKzgProof?: Uint8Array // This property should only be populated when the transaction is in the "Network Wrapper" format /** * This constructor takes the values, validates them, assigns them and freezes the object. @@ -111,9 +114,9 @@ export class BlobEIP4844Transaction extends BaseTransaction toBuffer(vh)) + this.versionedHashes = (txData.versionedHashes ?? []).map((vh) => toBytes(vh)) this._validateYParity() this._validateHighS() @@ -160,9 +163,9 @@ export class BlobEIP4844Transaction extends BaseTransaction toBuffer(blob)) - this.kzgCommitments = txData.kzgCommitments?.map((commitment) => toBuffer(commitment)) - this.aggregateKzgProof = toBuffer(txData.kzgProof) + this.blobs = txData.blobs?.map((blob) => toBytes(blob)) + this.kzgCommitments = txData.kzgCommitments?.map((commitment) => toBytes(commitment)) + this.aggregateKzgProof = toBytes(txData.kzgProof) const freeze = opts?.freeze ?? true if (freeze) { Object.freeze(this) @@ -199,14 +202,14 @@ export class BlobEIP4844Transaction extends BaseTransaction Buffer.from(key)) - const accessListItem: AccessListBufferItem = [address, storageKeys] + const accessListItem: AccessListBytesItem = [listItem.address, listItem.storageKeys] accessList.push(accessListItem) } const to = decodedTx.to.value === null ? undefined - : Address.fromString(bufferToHex(Buffer.from(decodedTx.to.value))) + : Address.fromString(bytesToPrefixedHexString(decodedTx.to.value)) - const versionedHashes = decodedTx.blobVersionedHashes.map((el) => Buffer.from(el)) - const commitments = wrapper.blobKzgs.map((el) => Buffer.from(el)) - const blobs = wrapper.blobs.map((el) => Buffer.from(el)) const txData = { ...decodedTx, ...{ - versionedHashes, + versionedHashes: decodedTx.blobVersionedHashes, accessList, to, - blobs, - kzgCommitments: commitments, - kzgProof: Buffer.from(wrapper.kzgAggregatedProof), + blobs: wrapper.blobKzgs, + kzgCommitments: wrapper.blobKzgs, + kzgProof: wrapper.kzgAggregatedProof, r: wrapper.tx.signature.r, s: wrapper.tx.signature.s, v: BigInt(wrapper.tx.signature.yParity), @@ -255,23 +253,20 @@ export class BlobEIP4844Transaction extends BaseTransaction Buffer.from(key)) - const accessListItem: AccessListBufferItem = [address, storageKeys] + const accessListItem: AccessListBytesItem = [listItem.address, listItem.storageKeys] accessList.push(accessListItem) } - const to = - tx.to.value === null ? undefined : Address.fromString(bufferToHex(Buffer.from(tx.to.value))) - const versionedHashes = tx.blobVersionedHashes.map((el) => Buffer.from(el)) + const to = tx.to.value === null ? undefined : Address.fromString(bytesToHex(tx.to.value)) + const versionedHashes = tx.blobVersionedHashes const txData = { ...tx, ...{ @@ -310,7 +305,7 @@ export class BlobEIP4844Transaction extends BaseTransaction { const to = { selector: this.to !== undefined ? 1 : 0, - value: this.to?.toBuffer() ?? null, + value: this.to?.toBytes() ?? null, } return { message: { @@ -341,15 +336,15 @@ export class BlobEIP4844Transaction extends BaseTransaction Uint8Array.from(blob)) ?? [] @@ -371,35 +366,35 @@ export class BlobEIP4844Transaction extends BaseTransaction bufferToHex(hash)), + versionedHashes: this.versionedHashes.map((hash) => bytesToHex(hash)), } } - _processSignature(v: bigint, r: Buffer, s: Buffer): BlobEIP4844Transaction { + _processSignature(v: bigint, r: Uint8Array, s: Uint8Array): BlobEIP4844Transaction { const opts = { ...this.txOptions, common: this.common } return BlobEIP4844Transaction.fromTxData( @@ -458,8 +453,8 @@ export class BlobEIP4844Transaction extends BaseTransaction { // strict byte length checking txParams.to = txParams.to !== null && txParams.to !== undefined - ? setLengthLeft(toBuffer(txParams.to), 20) + ? setLengthLeft(toBytes(txParams.to), 20) : null // Normalize the v/r/s values. If RPC returns '0x0', ensure v/r/s are set to `undefined` in the tx. diff --git a/packages/tx/src/legacyTransaction.ts b/packages/tx/src/legacyTransaction.ts index fa67af06bb..3933de928d 100644 --- a/packages/tx/src/legacyTransaction.ts +++ b/packages/tx/src/legacyTransaction.ts @@ -1,14 +1,13 @@ import { RLP } from '@ethereumjs/rlp' import { MAX_INTEGER, - arrToBufArr, bigIntToHex, - bigIntToUnpaddedBuffer, - bufArrToArr, - bufferToBigInt, + bigIntToUnpaddedBytes, + bytesToBigInt, + bytesToPrefixedHexString, ecrecover, - toBuffer, - unpadBuffer, + toBytes, + unpadBytes, validateNoLeadingZeroes, } from '@ethereumjs/util' import { keccak256 } from 'ethereum-cryptography/keccak' @@ -52,14 +51,14 @@ export class Transaction extends BaseTransaction { * * Format: `rlp([nonce, gasPrice, gasLimit, to, value, data, v, r, s])` */ - public static fromSerializedTx(serialized: Buffer, opts: TxOptions = {}) { - const values = arrToBufArr(RLP.decode(Uint8Array.from(serialized))) as Buffer[] + public static fromSerializedTx(serialized: Uint8Array, opts: TxOptions = {}) { + const values = RLP.decode(serialized) if (!Array.isArray(values)) { throw new Error('Invalid serialized tx input. Must be array') } - return this.fromValuesArray(values, opts) + return this.fromValuesArray(values as TxValuesArray, opts) } /** @@ -68,7 +67,7 @@ export class Transaction extends BaseTransaction { * Format: `[nonce, gasPrice, gasLimit, to, value, data, v, r, s]` */ public static fromValuesArray(values: TxValuesArray, opts: TxOptions = {}) { - // If length is not 6, it has length 9. If v/r/s are empty Buffers, it is still an unsigned transaction + // If length is not 6, it has length 9. If v/r/s are empty Uint8Arrays, it is still an unsigned transaction // This happens if you get the RLP data from `raw()` if (values.length !== 6 && values.length !== 9) { throw new Error( @@ -108,7 +107,7 @@ export class Transaction extends BaseTransaction { this.common = this._validateTxV(this.v, opts.common) - this.gasPrice = bufferToBigInt(toBuffer(txData.gasPrice === '' ? '0x' : txData.gasPrice)) + this.gasPrice = bytesToBigInt(toBytes(txData.gasPrice === '' ? '0x' : txData.gasPrice)) if (this.gasPrice * this.gasLimit > MAX_INTEGER) { const msg = this._errorMsg('gas limit * gasPrice cannot exceed MAX_INTEGER (2^256-1)') @@ -140,7 +139,7 @@ export class Transaction extends BaseTransaction { } /** - * Returns a Buffer Array of the raw Buffers of the legacy transaction, in order. + * Returns a Uint8Array Array of the raw Bytes of the legacy transaction, in order. * * Format: `[nonce, gasPrice, gasLimit, to, value, data, v, r, s]` * @@ -148,21 +147,21 @@ export class Transaction extends BaseTransaction { * to a block with {@link Block.fromValuesArray} (use the `serialize()` method * for typed txs). * - * For an unsigned tx this method returns the empty Buffer values + * For an unsigned tx this method returns the empty Bytes values * for the signature parameters `v`, `r` and `s`. For an EIP-155 compliant * representation have a look at {@link Transaction.getMessageToSign}. */ raw(): TxValuesArray { return [ - bigIntToUnpaddedBuffer(this.nonce), - bigIntToUnpaddedBuffer(this.gasPrice), - bigIntToUnpaddedBuffer(this.gasLimit), - this.to !== undefined ? this.to.buf : Buffer.from([]), - bigIntToUnpaddedBuffer(this.value), + bigIntToUnpaddedBytes(this.nonce), + bigIntToUnpaddedBytes(this.gasPrice), + bigIntToUnpaddedBytes(this.gasLimit), + this.to !== undefined ? this.to.bytes : new Uint8Array(0), + bigIntToUnpaddedBytes(this.value), this.data, - this.v !== undefined ? bigIntToUnpaddedBuffer(this.v) : Buffer.from([]), - this.r !== undefined ? bigIntToUnpaddedBuffer(this.r) : Buffer.from([]), - this.s !== undefined ? bigIntToUnpaddedBuffer(this.s) : Buffer.from([]), + this.v !== undefined ? bigIntToUnpaddedBytes(this.v) : new Uint8Array(0), + this.r !== undefined ? bigIntToUnpaddedBytes(this.r) : new Uint8Array(0), + this.s !== undefined ? bigIntToUnpaddedBytes(this.s) : new Uint8Array(0), ] } @@ -171,28 +170,28 @@ export class Transaction extends BaseTransaction { * * Format: `rlp([nonce, gasPrice, gasLimit, to, value, data, v, r, s])` * - * For an unsigned tx this method uses the empty Buffer values for the + * For an unsigned tx this method uses the empty Uint8Array values for the * signature parameters `v`, `r` and `s` for encoding. For an EIP-155 compliant * representation for external signing use {@link Transaction.getMessageToSign}. */ - serialize(): Buffer { - return Buffer.from(RLP.encode(bufArrToArr(this.raw()))) + serialize(): Uint8Array { + return RLP.encode(this.raw()) } private _getMessageToSign() { const values = [ - bigIntToUnpaddedBuffer(this.nonce), - bigIntToUnpaddedBuffer(this.gasPrice), - bigIntToUnpaddedBuffer(this.gasLimit), - this.to !== undefined ? this.to.buf : Buffer.from([]), - bigIntToUnpaddedBuffer(this.value), + bigIntToUnpaddedBytes(this.nonce), + bigIntToUnpaddedBytes(this.gasPrice), + bigIntToUnpaddedBytes(this.gasLimit), + this.to !== undefined ? this.to.bytes : new Uint8Array(0), + bigIntToUnpaddedBytes(this.value), this.data, ] if (this.supports(Capability.EIP155ReplayProtection)) { - values.push(toBuffer(this.common.chainId())) - values.push(unpadBuffer(toBuffer(0))) - values.push(unpadBuffer(toBuffer(0))) + values.push(toBytes(this.common.chainId())) + values.push(unpadBytes(toBytes(0))) + values.push(unpadBytes(toBytes(0))) } return values @@ -206,20 +205,19 @@ export class Transaction extends BaseTransaction { * and you might need to do yourself with: * * ```javascript - * import { bufArrToArr } from '@ethereumjs/util' * import { RLP } from '@ethereumjs/rlp' * const message = tx.getMessageToSign(false) - * const serializedMessage = Buffer.from(RLP.encode(bufArrToArr(message))) // use this for the HW wallet input + * const serializedMessage = RLP.encode(message)) // use this for the HW wallet input * ``` * * @param hashMessage - Return hashed message if set to true (default: true) */ - getMessageToSign(hashMessage: false): Buffer[] - getMessageToSign(hashMessage?: true): Buffer + getMessageToSign(hashMessage: false): Uint8Array[] + getMessageToSign(hashMessage?: true): Uint8Array getMessageToSign(hashMessage = true) { const message = this._getMessageToSign() if (hashMessage) { - return Buffer.from(keccak256(RLP.encode(bufArrToArr(message)))) + return keccak256(RLP.encode(message)) } else { return message } @@ -256,7 +254,7 @@ export class Transaction extends BaseTransaction { * This method can only be used for signed txs (it throws otherwise). * Use {@link Transaction.getMessageToSign} to get a tx hash for the purpose of signing. */ - hash(): Buffer { + hash(): Uint8Array { if (!this.isSigned()) { const msg = this._errorMsg('Cannot call hash method if transaction is not signed') throw new Error(msg) @@ -264,12 +262,12 @@ export class Transaction extends BaseTransaction { if (Object.isFrozen(this)) { if (!this.cache.hash) { - this.cache.hash = Buffer.from(keccak256(RLP.encode(bufArrToArr(this.raw())))) + this.cache.hash = keccak256(RLP.encode(this.raw())) } return this.cache.hash } - return Buffer.from(keccak256(RLP.encode(bufArrToArr(this.raw())))) + return keccak256(RLP.encode(this.raw())) } /** @@ -281,13 +279,13 @@ export class Transaction extends BaseTransaction { throw new Error(msg) } const message = this._getMessageToSign() - return Buffer.from(keccak256(RLP.encode(bufArrToArr(message)))) + return keccak256(RLP.encode(message)) } /** * Returns the public key of the sender */ - getSenderPublicKey(): Buffer { + getSenderPublicKey(): Uint8Array { const msgHash = this.getMessageToVerifySignature() const { v, r, s } = this @@ -298,8 +296,8 @@ export class Transaction extends BaseTransaction { return ecrecover( msgHash, v!, - bigIntToUnpaddedBuffer(r!), - bigIntToUnpaddedBuffer(s!), + bigIntToUnpaddedBytes(r!), + bigIntToUnpaddedBytes(s!), this.supports(Capability.EIP155ReplayProtection) ? this.common.chainId() : undefined ) } catch (e: any) { @@ -311,7 +309,7 @@ export class Transaction extends BaseTransaction { /** * Process the v, r, s values from the `sign` method of the base transaction. */ - protected _processSignature(v: bigint, r: Buffer, s: Buffer) { + protected _processSignature(v: bigint, r: Uint8Array, s: Uint8Array) { if (this.supports(Capability.EIP155ReplayProtection)) { v += this.common.chainId() * BigInt(2) + BigInt(8) } @@ -327,8 +325,8 @@ export class Transaction extends BaseTransaction { value: this.value, data: this.data, v, - r: bufferToBigInt(r), - s: bufferToBigInt(s), + r: bytesToBigInt(r), + s: bytesToBigInt(s), }, opts ) @@ -344,7 +342,7 @@ export class Transaction extends BaseTransaction { gasLimit: bigIntToHex(this.gasLimit), to: this.to !== undefined ? this.to.toString() : undefined, value: bigIntToHex(this.value), - data: '0x' + this.data.toString('hex'), + data: bytesToPrefixedHexString(this.data), v: this.v !== undefined ? bigIntToHex(this.v) : undefined, r: this.r !== undefined ? bigIntToHex(this.r) : undefined, s: this.s !== undefined ? bigIntToHex(this.s) : undefined, diff --git a/packages/tx/src/transactionFactory.ts b/packages/tx/src/transactionFactory.ts index 8d71890da1..5a76e5d91b 100644 --- a/packages/tx/src/transactionFactory.ts +++ b/packages/tx/src/transactionFactory.ts @@ -1,4 +1,4 @@ -import { bufferToBigInt, toBuffer } from '@ethereumjs/util' +import { bytesToBigInt, toBytes } from '@ethereumjs/util' import { JsonRpcProvider } from '@ethersproject/providers' import { FeeMarketEIP1559Transaction } from './eip1559Transaction' @@ -34,7 +34,7 @@ export class TransactionFactory { // Assume legacy transaction return Transaction.fromTxData(txData, txOptions) } else { - const txType = Number(bufferToBigInt(toBuffer(txData.type))) + const txType = Number(bytesToBigInt(toBytes(txData.type))) if (txType === 0) { return Transaction.fromTxData(txData, txOptions) } else if (txType === 1) { @@ -52,10 +52,10 @@ export class TransactionFactory { /** * This method tries to decode serialized data. * - * @param data - The data Buffer + * @param data - The data Uint8Array * @param txOptions - The transaction options */ - public static fromSerializedData(data: Buffer, txOptions: TxOptions = {}): TypedTransaction { + public static fromSerializedData(data: Uint8Array, txOptions: TxOptions = {}): TypedTransaction { if (data[0] <= 0x7f) { // Determine the type. switch (data[0]) { @@ -75,15 +75,15 @@ export class TransactionFactory { /** * When decoding a BlockBody, in the transactions field, a field is either: - * A Buffer (a TypedTransaction - encoded as TransactionType || rlp(TransactionPayload)) - * A Buffer[] (Legacy Transaction) + * A Uint8Array (a TypedTransaction - encoded as TransactionType || rlp(TransactionPayload)) + * A Uint8Array[] (Legacy Transaction) * This method returns the right transaction. * - * @param data - A Buffer or Buffer[] + * @param data - A Uint8Array or Uint8Array[] * @param txOptions - The transaction options */ - public static fromBlockBodyData(data: Buffer | Buffer[], txOptions: TxOptions = {}) { - if (Buffer.isBuffer(data)) { + public static fromBlockBodyData(data: Uint8Array | Uint8Array[], txOptions: TxOptions = {}) { + if (data instanceof Uint8Array) { return this.fromSerializedData(data, txOptions) } else if (Array.isArray(data)) { // It is a legacy transaction diff --git a/packages/tx/src/types.ts b/packages/tx/src/types.ts index d4aaff01fd..ebc95b241f 100644 --- a/packages/tx/src/types.ts +++ b/packages/tx/src/types.ts @@ -24,7 +24,7 @@ import type { AccessListEIP2930Transaction } from './eip2930Transaction' import type { BlobEIP4844Transaction } from './eip4844Transaction' import type { Transaction } from './legacyTransaction' import type { Common } from '@ethereumjs/common' -import type { AddressLike, BigIntLike, BufferLike, PrefixedHexString } from '@ethereumjs/util' +import type { AddressLike, BigIntLike, BytesLike, PrefixedHexString } from '@ethereumjs/util' const Bytes20 = new ByteVectorType(20) const Bytes32 = new ByteVectorType(32) @@ -108,15 +108,13 @@ export type AccessListItem = { } /* - * An Access List as a tuple of [address: Buffer, storageKeys: Buffer[]] + * An Access List as a tuple of [address: Uint8Array, storageKeys: Uint8Array[]] */ -export type AccessListBufferItem = [Buffer, Buffer[]] -export type AccessListBuffer = AccessListBufferItem[] +export type AccessListBytesItem = [Uint8Array, Uint8Array[]] +export type AccessListBytes = AccessListBytesItem[] export type AccessList = AccessListItem[] -export function isAccessListBuffer( - input: AccessListBuffer | AccessList -): input is AccessListBuffer { +export function isAccessListBytes(input: AccessListBytes | AccessList): input is AccessListBytes { if (input.length === 0) { return true } @@ -127,8 +125,8 @@ export function isAccessListBuffer( return false } -export function isAccessList(input: AccessListBuffer | AccessList): input is AccessList { - return !isAccessListBuffer(input) // This is exactly the same method, except the output is negated. +export function isAccessList(input: AccessListBytes | AccessList): input is AccessList { + return !isAccessListBytes(input) // This is exactly the same method, except the output is negated. } /** @@ -175,7 +173,7 @@ export type TxData = { /** * This will contain the data of the message or the init of a contract. */ - data?: BufferLike + data?: BytesLike /** * EC recovery ID. @@ -211,7 +209,7 @@ export interface AccessListEIP2930TxData extends TxData { /** * The access list which contains the addresses/storage slots which the transaction wishes to access */ - accessList?: AccessListBuffer | AccessList | null + accessList?: AccessListBytes | AccessList | null } /** @@ -240,7 +238,7 @@ export interface BlobEIP4844TxData extends FeeMarketEIP1559TxData { /** * The versioned hashes used to validate the blobs attached to a transaction */ - versionedHashes?: BufferLike[] + versionedHashes?: BytesLike[] /** * The maximum fee per data gas paid for the transaction */ @@ -248,55 +246,55 @@ export interface BlobEIP4844TxData extends FeeMarketEIP1559TxData { /** * The blobs associated with a transaction */ - blobs?: BufferLike[] + blobs?: BytesLike[] /** * The KZG commitments corresponding to the versioned hashes for each blob */ - kzgCommitments?: BufferLike[] + kzgCommitments?: BytesLike[] /** * The aggregate KZG proof associated with the transaction */ - kzgProof?: BufferLike + kzgProof?: BytesLike } /** * Buffer values array for a legacy {@link Transaction} */ -export type TxValuesArray = Buffer[] +export type TxValuesArray = Uint8Array[] /** * Buffer values array for an {@link AccessListEIP2930Transaction} */ export type AccessListEIP2930ValuesArray = [ - Buffer, - Buffer, - Buffer, - Buffer, - Buffer, - Buffer, - Buffer, - AccessListBuffer, - Buffer?, - Buffer?, - Buffer? + Uint8Array, + Uint8Array, + Uint8Array, + Uint8Array, + Uint8Array, + Uint8Array, + Uint8Array, + AccessListBytes, + Uint8Array?, + Uint8Array?, + Uint8Array? ] /** * Buffer values array for a {@link FeeMarketEIP1559Transaction} */ export type FeeMarketEIP1559ValuesArray = [ - Buffer, - Buffer, - Buffer, - Buffer, - Buffer, - Buffer, - Buffer, - Buffer, - AccessListBuffer, - Buffer?, - Buffer?, - Buffer? + Uint8Array, + Uint8Array, + Uint8Array, + Uint8Array, + Uint8Array, + Uint8Array, + Uint8Array, + Uint8Array, + AccessListBytes, + Uint8Array?, + Uint8Array?, + Uint8Array? ] type JsonAccessListItem = { address: string; storageKeys: string[] } diff --git a/packages/tx/src/util.ts b/packages/tx/src/util.ts index 958002c2d5..bded6cba96 100644 --- a/packages/tx/src/util.ts +++ b/packages/tx/src/util.ts @@ -1,9 +1,9 @@ -import { bufferToHex, setLengthLeft, toBuffer } from '@ethereumjs/util' +import { bytesToPrefixedHexString, hexStringToBytes, setLengthLeft } from '@ethereumjs/util' import { isAccessList } from './types' import type { BlobEIP4844Transaction } from './eip4844Transaction' -import type { AccessList, AccessListBuffer, AccessListItem } from './types' +import type { AccessList, AccessListBytes, AccessListItem } from './types' import type { Common } from '@ethereumjs/common' export function checkMaxInitCodeSize(common: Common, length: number) { @@ -19,21 +19,21 @@ export function checkMaxInitCodeSize(common: Common, length: number) { } export class AccessLists { - public static getAccessListData(accessList: AccessListBuffer | AccessList) { + public static getAccessListData(accessList: AccessListBytes | AccessList) { let AccessListJSON let bufferAccessList if (isAccessList(accessList)) { AccessListJSON = accessList - const newAccessList: AccessListBuffer = [] + const newAccessList: AccessListBytes = [] for (let i = 0; i < accessList.length; i++) { const item: AccessListItem = accessList[i] - const addressBuffer = toBuffer(item.address) - const storageItems: Buffer[] = [] + const addressBytes = hexStringToBytes(item.address) + const storageItems: Uint8Array[] = [] for (let index = 0; index < item.storageKeys.length; index++) { - storageItems.push(toBuffer(item.storageKeys[index])) + storageItems.push(hexStringToBytes(item.storageKeys[index])) } - newAccessList.push([addressBuffer, storageItems]) + newAccessList.push([addressBytes, storageItems]) } bufferAccessList = newAccessList } else { @@ -42,10 +42,10 @@ export class AccessLists { const json: AccessList = [] for (let i = 0; i < bufferAccessList.length; i++) { const data = bufferAccessList[i] - const address = bufferToHex(data[0]) + const address = bytesToPrefixedHexString(data[0]) const storageKeys: string[] = [] for (let item = 0; item < data[1].length; item++) { - storageKeys.push(bufferToHex(data[1][item])) + storageKeys.push(bytesToPrefixedHexString(data[1][item])) } const jsonItem: AccessListItem = { address, @@ -62,11 +62,11 @@ export class AccessLists { } } - public static verifyAccessList(accessList: AccessListBuffer) { + public static verifyAccessList(accessList: AccessListBytes) { for (let key = 0; key < accessList.length; key++) { const accessListItem = accessList[key] - const address = accessListItem[0] - const storageSlots = accessListItem[1] + const address = accessListItem[0] + const storageSlots = accessListItem[1] if ((accessListItem)[2] !== undefined) { throw new Error( 'Access list item cannot have 3 elements. It can only have an address, and an array of storage slots.' @@ -83,25 +83,25 @@ export class AccessLists { } } - public static getAccessListJSON(accessList: AccessListBuffer) { + public static getAccessListJSON(accessList: AccessListBytes) { const accessListJSON = [] for (let index = 0; index < accessList.length; index++) { const item: any = accessList[index] const JSONItem: any = { - address: '0x' + setLengthLeft(item[0], 20).toString('hex'), + address: bytesToPrefixedHexString(setLengthLeft(item[0], 20)), storageKeys: [], } - const storageSlots: Buffer[] = item[1] + const storageSlots: Uint8Array[] = item[1] for (let slot = 0; slot < storageSlots.length; slot++) { const storageSlot = storageSlots[slot] - JSONItem.storageKeys.push('0x' + setLengthLeft(storageSlot, 32).toString('hex')) + JSONItem.storageKeys.push(bytesToPrefixedHexString(setLengthLeft(storageSlot, 32))) } accessListJSON.push(JSONItem) } return accessListJSON } - public static getDataFeeEIP2930(accessList: AccessListBuffer, common: Common): number { + public static getDataFeeEIP2930(accessList: AccessListBytes, common: Common): number { const accessListStorageKeyCost = common.param('gasPrices', 'accessListStorageKeyCost') const accessListAddressCost = common.param('gasPrices', 'accessListAddressCost') @@ -120,7 +120,7 @@ export class AccessLists { export const blobTxToNetworkWrapperDataFormat = (tx: BlobEIP4844Transaction) => { const to = { selector: tx.to !== undefined ? 1 : 0, - value: tx.to?.toBuffer() ?? null, + value: tx.to?.toBytes() ?? null, } return { message: { diff --git a/packages/tx/src/utils/blobHelpers.ts b/packages/tx/src/utils/blobHelpers.ts index c3080da2c5..3e5808b609 100644 --- a/packages/tx/src/utils/blobHelpers.ts +++ b/packages/tx/src/utils/blobHelpers.ts @@ -1,4 +1,5 @@ import { sha256 } from 'ethereum-cryptography/sha256' +import { utf8ToBytes } from 'ethereum-cryptography/utils' import { kzg } from '../kzg/kzg' @@ -12,28 +13,27 @@ const MAX_BLOBS_PER_TX = 2 const MAX_USEFUL_BYTES_PER_TX = USEFUL_BYTES_PER_BLOB * MAX_BLOBS_PER_TX - 1 const BLOB_SIZE = BYTES_PER_FIELD_ELEMENT * FIELD_ELEMENTS_PER_BLOB -function get_padded(data: Buffer, blobs_len: number) { - const pdata = Buffer.alloc(blobs_len * USEFUL_BYTES_PER_BLOB) - const datalen = Buffer.byteLength(data) - pdata.fill(data, 0, datalen) - pdata[datalen] = 0x80 +function get_padded(data: Uint8Array, blobs_len: number): Uint8Array { + const pdata = new Uint8Array(blobs_len * USEFUL_BYTES_PER_BLOB).fill(0) + pdata.set(data) + pdata[data.byteLength] = 0x80 return pdata } -function get_blob(data: Buffer) { - const blob = Buffer.alloc(BLOB_SIZE, 'binary') +function get_blob(data: Uint8Array): Uint8Array { + const blob = new Uint8Array(BLOB_SIZE) for (let i = 0; i < FIELD_ELEMENTS_PER_BLOB; i++) { - const chunk = Buffer.alloc(32, 'binary') - chunk.fill(data.subarray(i * 31, (i + 1) * 31), 0, 31) - blob.fill(chunk, i * 32, (i + 1) * 32) + const chunk = new Uint8Array(32) + chunk.set(data.subarray(i * 31, (i + 1) * 31), 0) + blob.set(chunk, i * 32) } return blob } export const getBlobs = (input: string) => { - const data = Buffer.from(input, 'binary') - const len = Buffer.byteLength(data) + const data = utf8ToBytes(input) + const len = data.byteLength if (len === 0) { throw Error('invalid blob data') } @@ -45,7 +45,7 @@ export const getBlobs = (input: string) => { const pdata = get_padded(data, blobs_len) - const blobs = [] + const blobs: Uint8Array[] = [] for (let i = 0; i < blobs_len; i++) { const chunk = pdata.subarray(i * USEFUL_BYTES_PER_BLOB, (i + 1) * USEFUL_BYTES_PER_BLOB) const blob = get_blob(chunk) @@ -55,10 +55,10 @@ export const getBlobs = (input: string) => { return blobs } -export const blobsToCommitments = (blobs: Buffer[]) => { - const commitments = [] +export const blobsToCommitments = (blobs: Uint8Array[]) => { + const commitments: Uint8Array[] = [] for (const blob of blobs) { - commitments.push(Buffer.from(kzg.blobToKzgCommitment(blob))) + commitments.push(kzg.blobToKzgCommitment(blob)) } return commitments } @@ -74,7 +74,7 @@ export const blobsToCommitments = (blobs: Buffer[]) => { export const computeVersionedHash = (commitment: Uint8Array, blobCommitmentVersion: number) => { const computedVersionedHash = new Uint8Array(32) computedVersionedHash.set([blobCommitmentVersion], 0) - computedVersionedHash.set(sha256(commitment).slice(1), 1) + computedVersionedHash.set(sha256(commitment).subarray(1), 1) return computedVersionedHash } @@ -84,10 +84,10 @@ export const computeVersionedHash = (commitment: Uint8Array, blobCommitmentVersi * @returns array of versioned hashes * Note: assumes KZG commitments (version 1 version hashes) */ -export const commitmentsToVersionedHashes = (commitments: Buffer[]) => { - const hashes = [] +export const commitmentsToVersionedHashes = (commitments: Uint8Array[]) => { + const hashes: Uint8Array[] = [] for (const commitment of commitments) { - hashes.push(Buffer.from(computeVersionedHash(commitment, 0x01))) + hashes.push(computeVersionedHash(commitment, 0x01)) } return hashes } diff --git a/packages/tx/test/base.spec.ts b/packages/tx/test/base.spec.ts index ed8a89e587..4717acccde 100644 --- a/packages/tx/test/base.spec.ts +++ b/packages/tx/test/base.spec.ts @@ -3,9 +3,12 @@ import { MAX_INTEGER, MAX_UINT64, SECP256K1_ORDER, - bufferToBigInt, + bytesToBigInt, + equalsBytes, + hexStringToBytes, privateToPublic, - toBuffer, + toBytes, + utf8ToBytes, } from '@ethereumjs/util' import * as tape from 'tape' @@ -41,7 +44,7 @@ tape('[BaseTransaction]', function (t) { eip1559Txs.push(FeeMarketEIP1559Transaction.fromTxData(tx.data, { common })) } - const zero = Buffer.alloc(0) + const zero = new Uint8Array(0) const txTypes = [ { class: Transaction, @@ -62,7 +65,7 @@ tape('[BaseTransaction]', function (t) { class: AccessListEIP2930Transaction, name: 'AccessListEIP2930Transaction', type: 1, - values: [Buffer.from([1])].concat(Array(7).fill(zero)), + values: [new Uint8Array([1])].concat(Array(7).fill(zero)), txs: eip2930Txs, fixtures: eip2930Fixtures, activeCapabilities: [Capability.EIP2718TypedTransaction, Capability.EIP2930AccessLists], @@ -72,7 +75,7 @@ tape('[BaseTransaction]', function (t) { class: FeeMarketEIP1559Transaction, name: 'FeeMarketEIP1559Transaction', type: 2, - values: [Buffer.from([1])].concat(Array(8).fill(zero)), + values: [new Uint8Array([1])].concat(Array(8).fill(zero)), txs: eip1559Txs, fixtures: eip1559Fixtures, activeCapabilities: [ @@ -152,7 +155,7 @@ tape('[BaseTransaction]', function (t) { t.test('fromValuesArray()', function (st) { let rlpData: any = legacyTxs[0].raw() - rlpData[0] = toBuffer('0x0') + rlpData[0] = toBytes('0x0') try { Transaction.fromValuesArray(rlpData) st.fail('should have thrown when nonce has leading zeroes') @@ -162,8 +165,8 @@ tape('[BaseTransaction]', function (t) { 'should throw with nonce with leading zeroes' ) } - rlpData[0] = toBuffer('0x') - rlpData[6] = toBuffer('0x0') + rlpData[0] = toBytes('0x') + rlpData[6] = toBytes('0x0') try { Transaction.fromValuesArray(rlpData) st.fail('should have thrown when v has leading zeroes') @@ -174,7 +177,7 @@ tape('[BaseTransaction]', function (t) { ) } rlpData = eip2930Txs[0].raw() - rlpData[3] = toBuffer('0x0') + rlpData[3] = toBytes('0x0') try { AccessListEIP2930Transaction.fromValuesArray(rlpData) st.fail('should have thrown when gasLimit has leading zeroes') @@ -185,7 +188,7 @@ tape('[BaseTransaction]', function (t) { ) } rlpData = eip1559Txs[0].raw() - rlpData[2] = toBuffer('0x0') + rlpData[2] = toBytes('0x0') try { FeeMarketEIP1559Transaction.fromValuesArray(rlpData) st.fail('should have thrown when maxPriorityFeePerGas has leading zeroes') @@ -277,11 +280,11 @@ tape('[BaseTransaction]', function (t) { for (const [i, tx] of txType.txs.entries()) { const { privateKey } = txType.fixtures[i] if (privateKey !== undefined) { - st.ok(tx.sign(Buffer.from(privateKey, 'hex')), `${txType.name}: should sign tx`) + st.ok(tx.sign(hexStringToBytes(privateKey)), `${txType.name}: should sign tx`) } st.throws( - () => tx.sign(Buffer.from('invalid')), + () => tx.sign(utf8ToBytes('invalid')), `${txType.name}: should fail with invalid PK` ) } @@ -319,7 +322,7 @@ tape('[BaseTransaction]', function (t) { for (const [i, tx] of txType.txs.entries()) { const { privateKey, sendersAddress } = txType.fixtures[i] if (privateKey !== undefined) { - const signedTx = tx.sign(Buffer.from(privateKey, 'hex')) + const signedTx = tx.sign(hexStringToBytes(privateKey)) st.equal( signedTx.getSenderAddress().toString(), `0x${sendersAddress}`, @@ -336,11 +339,11 @@ tape('[BaseTransaction]', function (t) { for (const [i, tx] of txType.txs.entries()) { const { privateKey } = txType.fixtures[i] if (privateKey !== undefined) { - const signedTx = tx.sign(Buffer.from(privateKey, 'hex')) + const signedTx = tx.sign(hexStringToBytes(privateKey)) const txPubKey = signedTx.getSenderPublicKey() - const pubKeyFromPriv = privateToPublic(Buffer.from(privateKey, 'hex')) + const pubKeyFromPriv = privateToPublic(hexStringToBytes(privateKey)) st.ok( - txPubKey.equals(pubKeyFromPriv), + equalsBytes(txPubKey, pubKeyFromPriv), `${txType.name}: should get sender's public key after signing it` ) } @@ -358,7 +361,7 @@ tape('[BaseTransaction]', function (t) { for (const [i, tx] of txType.txs.entries()) { const { privateKey } = txType.fixtures[i] if (privateKey !== undefined) { - let signedTx = tx.sign(Buffer.from(privateKey, 'hex')) + let signedTx = tx.sign(hexStringToBytes(privateKey)) signedTx = JSON.parse(JSON.stringify(signedTx)) // deep clone ;(signedTx as any).s = SECP256K1_ORDER + BigInt(1) st.throws(() => { @@ -376,7 +379,7 @@ tape('[BaseTransaction]', function (t) { for (const [i, tx] of txType.txs.entries()) { const { privateKey } = txType.fixtures[i] if (privateKey !== undefined) { - const signedTx = tx.sign(Buffer.from(privateKey, 'hex')) + const signedTx = tx.sign(hexStringToBytes(privateKey)) st.ok(signedTx.verifySignature(), `${txType.name}: should verify signing it`) } } @@ -385,7 +388,7 @@ tape('[BaseTransaction]', function (t) { }) t.test('initialization with defaults', function (st) { - const bufferZero = toBuffer('0x') + const bufferZero = toBytes('0x') const tx = Transaction.fromTxData({ nonce: '', gasLimit: '', @@ -401,11 +404,11 @@ tape('[BaseTransaction]', function (t) { st.equal(tx.r, undefined) st.equal(tx.s, undefined) st.isEquivalent(tx.to, undefined) - st.isEquivalent(tx.value, bufferToBigInt(bufferZero)) + st.isEquivalent(tx.value, bytesToBigInt(bufferZero)) st.isEquivalent(tx.data, bufferZero) - st.isEquivalent(tx.gasPrice, bufferToBigInt(bufferZero)) - st.isEquivalent(tx.gasLimit, bufferToBigInt(bufferZero)) - st.isEquivalent(tx.nonce, bufferToBigInt(bufferZero)) + st.isEquivalent(tx.gasPrice, bytesToBigInt(bufferZero)) + st.isEquivalent(tx.gasLimit, bytesToBigInt(bufferZero)) + st.isEquivalent(tx.nonce, bytesToBigInt(bufferZero)) st.end() }) diff --git a/packages/tx/test/eip1559.spec.ts b/packages/tx/test/eip1559.spec.ts index 458711cab8..4312cf12cb 100644 --- a/packages/tx/test/eip1559.spec.ts +++ b/packages/tx/test/eip1559.spec.ts @@ -1,6 +1,6 @@ import { Chain, Common, Hardfork } from '@ethereumjs/common' import { RLP } from '@ethereumjs/rlp' -import { TWO_POW256 } from '@ethereumjs/util' +import { TWO_POW256, equalsBytes, hexStringToBytes } from '@ethereumjs/util' import * as tape from 'tape' import { FeeMarketEIP1559Transaction } from '../src' @@ -12,8 +12,8 @@ const common = new Common({ hardfork: Hardfork.London, }) -const validAddress = Buffer.from('01'.repeat(20), 'hex') -const validSlot = Buffer.from('01'.repeat(32), 'hex') +const validAddress = hexStringToBytes('01'.repeat(20)) +const validSlot = hexStringToBytes('01'.repeat(32)) const chainId = BigInt(4) tape('[FeeMarketEIP1559Transaction]', function (t) { @@ -92,12 +92,12 @@ tape('[FeeMarketEIP1559Transaction]', function (t) { t.test('sign()', function (st) { for (let index = 0; index < testdata.length; index++) { const data = testdata[index] - const pkey = Buffer.from(data.privateKey.slice(2), 'hex') + const pkey = hexStringToBytes(data.privateKey) const txn = FeeMarketEIP1559Transaction.fromTxData(data, { common }) const signed = txn.sign(pkey) - const rlpSerialized = Buffer.from(RLP.encode(Uint8Array.from(signed.serialize()))) + const rlpSerialized = RLP.encode(Uint8Array.from(signed.serialize())) st.ok( - rlpSerialized.equals(Buffer.from(data.signedTransactionRLP.slice(2), 'hex')), + equalsBytes(rlpSerialized, hexStringToBytes(data.signedTransactionRLP)), 'Should sign txs correctly' ) } @@ -106,23 +106,25 @@ tape('[FeeMarketEIP1559Transaction]', function (t) { t.test('hash()', function (st) { const data = testdata[0] - const pkey = Buffer.from(data.privateKey.slice(2), 'hex') + const pkey = hexStringToBytes(data.privateKey) let txn = FeeMarketEIP1559Transaction.fromTxData(data, { common }) let signed = txn.sign(pkey) - const expectedHash = Buffer.from( - '2e564c87eb4b40e7f469b2eec5aa5d18b0b46a24e8bf0919439cfb0e8fcae446', - 'hex' + const expectedHash = hexStringToBytes( + '2e564c87eb4b40e7f469b2eec5aa5d18b0b46a24e8bf0919439cfb0e8fcae446' ) - st.ok(signed.hash().equals(expectedHash), 'Should provide the correct hash when frozen') + st.ok(equalsBytes(signed.hash(), expectedHash), 'Should provide the correct hash when frozen') txn = FeeMarketEIP1559Transaction.fromTxData(data, { common, freeze: false }) signed = txn.sign(pkey) - st.ok(signed.hash().equals(expectedHash), 'Should provide the correct hash when not frozen') + st.ok( + equalsBytes(signed.hash(), expectedHash), + 'Should provide the correct hash when not frozen' + ) st.end() }) t.test('freeze property propagates from unsigned tx to signed tx', function (st) { const data = testdata[0] - const pkey = Buffer.from(data.privateKey.slice(2), 'hex') + const pkey = hexStringToBytes(data.privateKey) const txn = FeeMarketEIP1559Transaction.fromTxData(data, { common, freeze: false }) st.notOk(Object.isFrozen(txn), 'tx object is not frozen') const signedTxn = txn.sign(pkey) @@ -132,7 +134,7 @@ tape('[FeeMarketEIP1559Transaction]', function (t) { t.test('common propagates from the common of tx, not the common in TxOptions', function (st) { const data = testdata[0] - const pkey = Buffer.from(data.privateKey.slice(2), 'hex') + const pkey = hexStringToBytes(data.privateKey) const txn = FeeMarketEIP1559Transaction.fromTxData(data, { common, freeze: false }) const newCommon = new Common({ chain: Chain.Rinkeby, hardfork: Hardfork.London, eips: [2537] }) st.notDeepEqual(newCommon, common, 'new common is different than original common') @@ -149,22 +151,20 @@ tape('[FeeMarketEIP1559Transaction]', function (t) { t.test('unsigned tx -> getMessageToSign()', function (t) { const unsignedTx = FeeMarketEIP1559Transaction.fromTxData( { - data: Buffer.from('010200', 'hex'), + data: hexStringToBytes('010200'), to: validAddress, accessList: [[validAddress, [validSlot]]], chainId, }, { common } ) - const expectedHash = Buffer.from( - 'fa81814f7dd57bad435657a05eabdba2815f41e3f15ddd6139027e7db56b0dea', - 'hex' + const expectedHash = hexStringToBytes( + 'fa81814f7dd57bad435657a05eabdba2815f41e3f15ddd6139027e7db56b0dea' ) t.deepEqual(unsignedTx.getMessageToSign(true), expectedHash), 'correct hashed version' - const expectedSerialization = Buffer.from( - '02f85904808080809401010101010101010101010101010101010101018083010200f838f7940101010101010101010101010101010101010101e1a00101010101010101010101010101010101010101010101010101010101010101', - 'hex' + const expectedSerialization = hexStringToBytes( + '02f85904808080809401010101010101010101010101010101010101018083010200f838f7940101010101010101010101010101010101010101e1a00101010101010101010101010101010101010101010101010101010101010101' ) t.deepEqual( unsignedTx.getMessageToSign(false), @@ -177,7 +177,7 @@ tape('[FeeMarketEIP1559Transaction]', function (t) { t.test('toJSON()', function (st) { const data = testdata[0] - const pkey = Buffer.from(data.privateKey.slice(2), 'hex') + const pkey = hexStringToBytes(data.privateKey) const txn = FeeMarketEIP1559Transaction.fromTxData(data, { common }) const signed = txn.sign(pkey) diff --git a/packages/tx/test/eip3860.spec.ts b/packages/tx/test/eip3860.spec.ts index 6556d8c674..b1cbaf92a6 100644 --- a/packages/tx/test/eip3860.spec.ts +++ b/packages/tx/test/eip3860.spec.ts @@ -16,7 +16,7 @@ const addressZero = Address.zero() tape('[EIP3860 tests]', function (t) { t.test('Should instantiate create txs with MAX_INITCODE_SIZE', (st) => { - const data = Buffer.alloc(Number(maxInitCodeSize)) + const data = new Uint8Array(Number(maxInitCodeSize)) for (const txType of txTypes) { try { TransactionFactory.fromTxData({ data, type: txType }, { common }) @@ -29,7 +29,7 @@ tape('[EIP3860 tests]', function (t) { }) t.test('Should instantiate txs with MAX_INITCODE_SIZE data', (st) => { - const data = Buffer.alloc(Number(maxInitCodeSize)) + const data = new Uint8Array(Number(maxInitCodeSize)) for (const txType of txTypes) { try { TransactionFactory.fromTxData({ data, type: txType, to: addressZero }, { common }) @@ -42,7 +42,7 @@ tape('[EIP3860 tests]', function (t) { }) t.test('Should not instantiate create txs with MAX_INITCODE_SIZE+1 data', (st) => { - const data = Buffer.alloc(Number(maxInitCodeSize) + 1) + const data = new Uint8Array(Number(maxInitCodeSize) + 1) for (const txType of txTypes) { try { TransactionFactory.fromTxData({ data, type: txType }, { common }) @@ -55,7 +55,7 @@ tape('[EIP3860 tests]', function (t) { }) t.test('Should instantiate txs with MAX_INITCODE_SIZE+1 data', (st) => { - const data = Buffer.alloc(Number(maxInitCodeSize) + 1) + const data = new Uint8Array(Number(maxInitCodeSize) + 1) for (const txType of txTypes) { try { TransactionFactory.fromTxData({ data, type: txType, to: addressZero }, { common }) @@ -70,7 +70,7 @@ tape('[EIP3860 tests]', function (t) { tape( 'Should allow txs with MAX_INITCODE_SIZE+1 data if allowUnlimitedInitCodeSize is active', (st) => { - const data = Buffer.alloc(Number(maxInitCodeSize) + 1) + const data = new Uint8Array(Number(maxInitCodeSize) + 1) for (const txType of txTypes) { try { TransactionFactory.fromTxData( @@ -87,7 +87,7 @@ tape('[EIP3860 tests]', function (t) { ) tape('Should charge initcode analysis gas is allowUnlimitedInitCodeSize is active', (st) => { - const data = Buffer.alloc(Number(maxInitCodeSize)) + const data = new Uint8Array(Number(maxInitCodeSize)) for (const txType of txTypes) { const eip3860ActiveTx = TransactionFactory.fromTxData( { data, type: txType }, diff --git a/packages/tx/test/eip4844.spec.ts b/packages/tx/test/eip4844.spec.ts index f5cb98bb3d..78138a8f77 100644 --- a/packages/tx/test/eip4844.spec.ts +++ b/packages/tx/test/eip4844.spec.ts @@ -1,6 +1,12 @@ import { Common, Hardfork } from '@ethereumjs/common' +import { + bytesToHex, + concatBytes, + equalsBytes, + hexStringToBytes, + randomBytes, +} from '@ethereumjs/util' import * as kzg from 'c-kzg' -import { randomBytes } from 'crypto' import * as tape from 'tape' import { BlobEIP4844Transaction, TransactionFactory, initKZG } from '../src' @@ -28,7 +34,7 @@ tape('EIP4844 constructor tests - valid scenarios', (t) => { } else { const txData = { type: 0x05, - versionedHashes: [Buffer.concat([Buffer.from([1]), randomBytes(31)])], + versionedHashes: [concatBytes(new Uint8Array([1]), randomBytes(31))], maxFeePerDataGas: 1n, } const tx = BlobEIP4844Transaction.fromTxData(txData, { common }) @@ -90,9 +96,9 @@ tape('fromTxData using from a json', (t) => { t.pass('Should be able to parse a json data and hash it') t.equal(typeof tx.maxFeePerDataGas, 'bigint', 'should be able to parse correctly') - t.equal(tx.serialize().toString('hex'), txData.serialized, 'serialization should match') + t.equal(bytesToHex(tx.serialize()), txData.serialized, 'serialization should match') // TODO: fix the hash - t.equal(tx.hash().toString('hex'), txData.hash, 'hash should match') + t.equal(bytesToHex(tx.hash()), txData.hash, 'hash should match') } catch (e) { t.fail('failed to parse json data') } @@ -110,16 +116,16 @@ tape('EIP4844 constructor tests - invalid scenarios', (t) => { maxFeePerDataGas: 1n, } const shortVersionHash = { - versionedHashes: [Buffer.concat([Buffer.from([3]), randomBytes(3)])], + versionedHashes: [concatBytes(new Uint8Array([3]), randomBytes(3))], } const invalidVersionHash = { - versionedHashes: [Buffer.concat([Buffer.from([3]), randomBytes(31)])], + versionedHashes: [concatBytes(new Uint8Array([3]), randomBytes(31))], } const tooManyBlobs = { versionedHashes: [ - Buffer.concat([Buffer.from([1]), randomBytes(31)]), - Buffer.concat([Buffer.from([1]), randomBytes(31)]), - Buffer.concat([Buffer.from([1]), randomBytes(31)]), + concatBytes(new Uint8Array([1]), randomBytes(31)), + concatBytes(new Uint8Array([1]), randomBytes(31)), + concatBytes(new Uint8Array([1]), randomBytes(31)), ], } try { @@ -155,19 +161,19 @@ tape('Network wrapper tests', async (t) => { const commitments = blobsToCommitments(blobs) const versionedHashes = commitmentsToVersionedHashes(commitments) const proof = kzg.computeAggregateKzgProof(blobs) - const bufferedHashes = versionedHashes.map((el) => Buffer.from(el)) const unsignedTx = BlobEIP4844Transaction.fromTxData( { - versionedHashes: bufferedHashes, + versionedHashes, blobs, kzgCommitments: commitments, - kzgProof: Buffer.from(proof), + kzgProof: proof, maxFeePerDataGas: 100000000n, gasLimit: 0xffffffn, to: randomBytes(20), }, { common } ) + const signedTx = unsignedTx.sign(pk) const sender = signedTx.getSenderAddress().toString() const wrapper = signedTx.serializeNetworkWrapper() @@ -189,13 +195,13 @@ tape('Network wrapper tests', async (t) => { const minimalTx = BlobEIP4844Transaction.minimalFromNetworkWrapper(deserializedTx, { common }) t.ok(minimalTx.blobs === undefined, 'minimal representation contains no blobs') t.ok( - minimalTx.hash().equals(deserializedTx.hash()), + equalsBytes(minimalTx.hash(), deserializedTx.hash()), 'has the same hash as the network wrapper version' ) const txWithMissingBlob = BlobEIP4844Transaction.fromTxData( { - versionedHashes: bufferedHashes, + versionedHashes, blobs: blobs.slice(1), kzgCommitments: commitments, maxFeePerDataGas: 100000000n, @@ -221,7 +227,7 @@ tape('Network wrapper tests', async (t) => { commitments[0][0] = 154 const txWithInvalidCommitment = BlobEIP4844Transaction.fromTxData( { - versionedHashes: bufferedHashes, + versionedHashes, blobs, kzgCommitments: commitments, maxFeePerDataGas: 100000000n, @@ -241,15 +247,15 @@ tape('Network wrapper tests', async (t) => { 'throws when kzg proof cant be verified' ) - bufferedHashes[0][1] = 2 + versionedHashes[0][1] = 2 commitments[0][0] = mangledValue const txWithInvalidVersionedHashes = BlobEIP4844Transaction.fromTxData( { - versionedHashes: bufferedHashes, + versionedHashes, blobs, kzgCommitments: commitments, - kzgProof: Buffer.from(proof), + kzgProof: proof, maxFeePerDataGas: 100000000n, gasLimit: 0xffffffn, to: randomBytes(20), @@ -283,7 +289,7 @@ tape('hash() and signature verification', async (t) => { chainId: 1, nonce: 1, versionedHashes: [ - Buffer.from('01624652859a6e98ffc1608e2af0147ca4e86e1ce27672d8d3f3c9d4ffd6ef7e', 'hex'), + hexStringToBytes('01624652859a6e98ffc1608e2af0147ca4e86e1ce27672d8d3f3c9d4ffd6ef7e'), ], maxFeePerDataGas: 10000000n, gasLimit: 123457n, @@ -299,12 +305,12 @@ tape('hash() and signature verification', async (t) => { { common } ) t.equal( - unsignedTx.unsignedHash().toString('hex'), + bytesToHex(unsignedTx.unsignedHash()), '0fcee5b30088a9c96b4990a3914002736a50f42468209d65a93badd3d1cd0677', 'produced the correct transaction hash' ) const signedTx = unsignedTx.sign( - Buffer.from('45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8', 'hex') + hexStringToBytes('45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8') ) t.equal( diff --git a/packages/tx/test/fromRpc.spec.ts b/packages/tx/test/fromRpc.spec.ts index f6b73d042c..9e10c1da7c 100644 --- a/packages/tx/test/fromRpc.spec.ts +++ b/packages/tx/test/fromRpc.spec.ts @@ -1,4 +1,5 @@ import { Chain, Common, Hardfork } from '@ethereumjs/common' +import { bytesToHex, bytesToPrefixedHexString } from '@ethereumjs/util' import * as tape from 'tape' import { TransactionFactory } from '../src' @@ -16,7 +17,7 @@ tape('[fromEthersProvider]', async (t) => { const txHash = '0xed1960aa7d0d7b567c946d94331dddb37a1c67f51f30bf51f256ea40db88cfb0' const tx = await TransactionFactory.fromEthersProvider(provider, txHash, { common }) t.equal( - '0x' + tx.hash().toString('hex'), + bytesToPrefixedHexString(tx.hash()), txHash, 'generated correct tx from transaction RPC data' ) @@ -29,7 +30,7 @@ tape('[normalizeTxParams]', (t) => { const tx = TransactionFactory.fromTxData(normedTx) t.equal(normedTx.gasLimit, 21000n, 'correctly converted "gas" to "gasLimit"') t.equal( - tx.hash().toString('hex'), + bytesToHex(tx.hash()), rpcTx.hash.slice(2), 'converted normed tx data to transaction objec' ) diff --git a/packages/tx/test/inputValue.spec.ts b/packages/tx/test/inputValue.spec.ts index e591d3d546..0433e2e6a3 100644 --- a/packages/tx/test/inputValue.spec.ts +++ b/packages/tx/test/inputValue.spec.ts @@ -1,5 +1,5 @@ import { Chain, Common, Hardfork } from '@ethereumjs/common' -import { Address, toBuffer } from '@ethereumjs/util' +import { Address, hexStringToBytes, toBytes } from '@ethereumjs/util' import * as tape from 'tape' import { @@ -14,21 +14,21 @@ import type { FeeMarketEIP1559ValuesArray, TxValuesArray, } from '../src' -import type { AddressLike, BigIntLike, BufferLike } from '@ethereumjs/util' +import type { AddressLike, BigIntLike, BytesLike } from '@ethereumjs/util' // @returns: Array with subtypes of the AddressLike type for a given address function generateAddressLikeValues(address: string): AddressLike[] { - return [address, toBuffer(address), new Address(toBuffer(address))] + return [address, toBytes(address), new Address(toBytes(address))] } // @returns: Array with subtypes of the BigIntLike type for a given number function generateBigIntLikeValues(value: number): BigIntLike[] { - return [value, BigInt(value), `0x${value.toString(16)}`, toBuffer(value)] + return [value, BigInt(value), `0x${value.toString(16)}`, toBytes(value)] } -// @returns: Array with subtypes of the BufferLike type for a given string -function generateBufferLikeValues(value: string): BufferLike[] { - return [value, toBuffer(value)] +// @returns: Array with subtypes of the BytesLike type for a given string +function generateBytesLikeValues(value: string): BytesLike[] { + return [value, toBytes(value)] } interface GenerateCombinationsArgs { @@ -89,7 +89,7 @@ function getRandomSubarray(array: TArrayItem[], size: number) { } const baseTxValues = { - data: generateBufferLikeValues('0x65'), + data: generateBytesLikeValues('0x65'), gasLimit: generateBigIntLikeValues(100000), nonce: generateBigIntLikeValues(0), to: generateAddressLikeValues('0x0000000000000000000000000000000000000000'), @@ -153,7 +153,7 @@ tape('[Invalid Array Input values]', (t) => { for (const txType of txTypes) { let tx = TransactionFactory.fromTxData({ type: txType }) if (signed) { - tx = tx.sign(Buffer.from('42'.repeat(32), 'hex')) + tx = tx.sign(hexStringToBytes('42'.repeat(32))) } const rawValues = tx.raw() for (let x = 0; x < rawValues.length; x++) { @@ -215,14 +215,14 @@ tape('[Invalid Access Lists]', (t) => { accessList: invalidAccessListItem, }) if (signed) { - tx = tx.sign(Buffer.from('42'.repeat(32), 'hex')) + tx = tx.sign(hexStringToBytes('42'.repeat(32))) } t.fail('did not fail on `fromTxData`') } catch (e: any) { t.pass('failed ok on decoding in `fromTxData`') tx = TransactionFactory.fromTxData({ type: txType }) if (signed) { - tx = tx.sign(Buffer.from('42'.repeat(32), 'hex')) + tx = tx.sign(hexStringToBytes('42'.repeat(32))) } } const rawValues = tx!.raw() diff --git a/packages/tx/test/legacy.spec.ts b/packages/tx/test/legacy.spec.ts index 7f9642c76f..096313834d 100644 --- a/packages/tx/test/legacy.spec.ts +++ b/packages/tx/test/legacy.spec.ts @@ -1,14 +1,15 @@ import { Chain, Common, Hardfork } from '@ethereumjs/common' import { RLP } from '@ethereumjs/rlp' import { - arrToBufArr, - bufferToBigInt, - bufferToHex, - intToBuffer, - toBuffer, - unpadBuffer, + bytesToBigInt, + bytesToHex, + bytesToPrefixedHexString, + equalsBytes, + hexStringToBytes, + intToBytes, + toBytes, + unpadBytes, } from '@ethereumjs/util' -import { Buffer } from 'buffer' import * as tape from 'tape' import { Transaction } from '../src' @@ -62,22 +63,22 @@ tape('[Transaction]', function (t) { 'should initialize on a pre-Berlin Harfork (EIP-2930 not activated)' ) - const txData = txFixtures[3].raw.map(toBuffer) - txData[6] = intToBuffer(45) // v with 0-parity and chain ID 5 + const txData = txFixtures[3].raw.map(toBytes) + txData[6] = intToBytes(45) // v with 0-parity and chain ID 5 let tx = Transaction.fromValuesArray(txData) st.ok( tx.common.chainId() === BigInt(5), 'should initialize Common with chain ID (supported) derived from v value (v with 0-parity)' ) - txData[6] = intToBuffer(46) // v with 1-parity and chain ID 5 + txData[6] = intToBytes(46) // v with 1-parity and chain ID 5 tx = Transaction.fromValuesArray(txData) st.ok( tx.common.chainId() === BigInt(5), 'should initialize Common with chain ID (supported) derived from v value (v with 1-parity)' ) - txData[6] = intToBuffer(2033) // v with 0-parity and chain ID 999 + txData[6] = intToBytes(2033) // v with 0-parity and chain ID 999 tx = Transaction.fromValuesArray(txData) st.equal( tx.common.chainId(), @@ -85,7 +86,7 @@ tape('[Transaction]', function (t) { 'should initialize Common with chain ID (unsupported) derived from v value (v with 0-parity)' ) - txData[6] = intToBuffer(2034) // v with 1-parity and chain ID 999 + txData[6] = intToBytes(2034) // v with 1-parity and chain ID 999 tx = Transaction.fromValuesArray(txData) st.equal( tx.common.chainId(), @@ -97,18 +98,18 @@ tape('[Transaction]', function (t) { t.test('Initialization -> decode with fromValuesArray()', function (st) { for (const tx of txFixtures.slice(0, 4)) { - const txData = tx.raw.map(toBuffer) + const txData = tx.raw.map(toBytes) const pt = Transaction.fromValuesArray(txData) - st.equal(bufferToHex(unpadBuffer(toBuffer(pt.nonce))), tx.raw[0]) - st.equal(bufferToHex(toBuffer(pt.gasPrice)), tx.raw[1]) - st.equal(bufferToHex(toBuffer(pt.gasLimit)), tx.raw[2]) + st.equal(bytesToPrefixedHexString(unpadBytes(toBytes(pt.nonce))), tx.raw[0]) + st.equal(bytesToPrefixedHexString(toBytes(pt.gasPrice)), tx.raw[1]) + st.equal(bytesToPrefixedHexString(toBytes(pt.gasLimit)), tx.raw[2]) st.equal(pt.to?.toString(), tx.raw[3]) - st.equal(bufferToHex(unpadBuffer(toBuffer(pt.value))), tx.raw[4]) - st.equal('0x' + pt.data.toString('hex'), tx.raw[5]) - st.equal(bufferToHex(toBuffer(pt.v)), tx.raw[6]) - st.equal(bufferToHex(toBuffer(pt.r)), tx.raw[7]) - st.equal(bufferToHex(toBuffer(pt.s)), tx.raw[8]) + st.equal(bytesToPrefixedHexString(unpadBytes(toBytes(pt.value))), tx.raw[4]) + st.equal(bytesToPrefixedHexString(pt.data), tx.raw[5]) + st.equal(bytesToPrefixedHexString(toBytes(pt.v)), tx.raw[6]) + st.equal(bytesToPrefixedHexString(toBytes(pt.r)), tx.raw[7]) + st.equal(bytesToPrefixedHexString(toBytes(pt.s)), tx.raw[8]) transactions.push(pt) } @@ -116,7 +117,7 @@ tape('[Transaction]', function (t) { }) t.test('Initialization -> should accept lesser r values', function (st) { - const tx = Transaction.fromTxData({ r: bufferToBigInt(toBuffer('0x0005')) }) + const tx = Transaction.fromTxData({ r: bytesToBigInt(toBytes('0x0005')) }) st.equal(tx.r!.toString(16), '5') st.end() }) @@ -127,7 +128,7 @@ tape('[Transaction]', function (t) { let common = new Common({ chain: Chain.Goerli, hardfork: Hardfork.Petersburg }) let tx = Transaction.fromTxData({}, { common }) st.equal(tx.common.chainId(), BigInt(5)) - const privKey = Buffer.from(txFixtures[0].privateKey, 'hex') + const privKey = hexStringToBytes(txFixtures[0].privateKey) tx = tx.sign(privKey) const serialized = tx.serialize() common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Petersburg }) @@ -164,10 +165,10 @@ tape('[Transaction]', function (t) { let tx = Transaction.fromTxData({}) st.equal(tx.getDataFee(), BigInt(0)) - tx = Transaction.fromValuesArray(txFixtures[3].raw.map(toBuffer)) + tx = Transaction.fromValuesArray(txFixtures[3].raw.map(toBytes)) st.equal(tx.getDataFee(), BigInt(1716)) - tx = Transaction.fromValuesArray(txFixtures[3].raw.map(toBuffer), { freeze: false }) + tx = Transaction.fromValuesArray(txFixtures[3].raw.map(toBytes), { freeze: false }) st.equal(tx.getDataFee(), BigInt(1716)) st.end() @@ -178,7 +179,7 @@ tape('[Transaction]', function (t) { let tx = Transaction.fromTxData({}, { common }) st.equal(tx.getDataFee(), BigInt(0)) - tx = Transaction.fromValuesArray(txFixtures[3].raw.map(toBuffer), { + tx = Transaction.fromValuesArray(txFixtures[3].raw.map(toBytes), { common, }) st.equal(tx.getDataFee(), BigInt(1716)) @@ -188,7 +189,7 @@ tape('[Transaction]', function (t) { t.test('getDataFee() -> should invalidate cached value on hardfork change', function (st) { const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Byzantium }) - const tx = Transaction.fromValuesArray(txFixtures[0].raw.map(toBuffer), { + const tx = Transaction.fromValuesArray(txFixtures[0].raw.map(toBytes), { common, }) st.equal(tx.getDataFee(), BigInt(656)) @@ -210,8 +211,8 @@ tape('[Transaction]', function (t) { t.test('serialize()', function (st) { for (const [i, tx] of transactions.entries()) { const s1 = tx.serialize() - const s2 = Buffer.from(RLP.encode(txFixtures[i].raw)) - st.ok(s1.equals(s2)) + const s2 = RLP.encode(txFixtures[i].raw) + st.ok(equalsBytes(s1, s2)) } st.end() }) @@ -220,11 +221,10 @@ tape('[Transaction]', function (t) { const tx = Transaction.fromTxData({ value: 5000 }) const s1 = tx.serialize() - const s1Rlp = toBuffer('0x' + s1.toString('hex')) - const tx2 = Transaction.fromSerializedTx(s1Rlp) + const tx2 = Transaction.fromSerializedTx(s1) const s2 = tx2.serialize() - st.ok(s1.equals(s2)) + st.ok(equalsBytes(s1, s2)) st.end() }) @@ -234,43 +234,43 @@ tape('[Transaction]', function (t) { hardfork: Hardfork.TangerineWhistle, }) - let tx = Transaction.fromValuesArray(txFixtures[3].raw.slice(0, 6).map(toBuffer), { + let tx = Transaction.fromValuesArray(txFixtures[3].raw.slice(0, 6).map(toBytes), { common, }) st.throws(() => { tx.hash() }, 'should throw calling hash with unsigned tx') - tx = Transaction.fromValuesArray(txFixtures[3].raw.map(toBuffer), { + tx = Transaction.fromValuesArray(txFixtures[3].raw.map(toBytes), { common, }) st.deepEqual( tx.hash(), - Buffer.from('375a8983c9fc56d7cfd118254a80a8d7403d590a6c9e105532b67aca1efb97aa', 'hex') + hexStringToBytes('375a8983c9fc56d7cfd118254a80a8d7403d590a6c9e105532b67aca1efb97aa') ) st.deepEqual( tx.getMessageToSign(), - Buffer.from('61e1ec33764304dddb55348e7883d4437426f44ab3ef65e6da1e025734c03ff0', 'hex') + hexStringToBytes('61e1ec33764304dddb55348e7883d4437426f44ab3ef65e6da1e025734c03ff0') ) st.equal(tx.getMessageToSign(false).length, 6) st.deepEqual( tx.hash(), - Buffer.from('375a8983c9fc56d7cfd118254a80a8d7403d590a6c9e105532b67aca1efb97aa', 'hex') + hexStringToBytes('375a8983c9fc56d7cfd118254a80a8d7403d590a6c9e105532b67aca1efb97aa') ) st.end() }) t.test('hash() -> with defined chainId', function (st) { - const tx = Transaction.fromValuesArray(txFixtures[4].raw.map(toBuffer)) + const tx = Transaction.fromValuesArray(txFixtures[4].raw.map(toBytes)) st.equal( - tx.hash().toString('hex'), + bytesToHex(tx.hash()), '0f09dc98ea85b7872f4409131a790b91e7540953992886fc268b7ba5c96820e4' ) st.equal( - tx.hash().toString('hex'), + bytesToHex(tx.hash()), '0f09dc98ea85b7872f4409131a790b91e7540953992886fc268b7ba5c96820e4' ) st.equal( - tx.getMessageToSign().toString('hex'), + bytesToHex(tx.getMessageToSign()), 'f97c73fdca079da7652dbc61a46cd5aeef804008e057be3e712c43eac389aaf0' ) st.end() @@ -280,9 +280,9 @@ tape('[Transaction]', function (t) { "getMessageToSign(), getSenderPublicKey() (implicit call) -> verify EIP155 signature based on Vitalik's tests", function (st) { for (const tx of txFixturesEip155) { - const pt = Transaction.fromSerializedTx(toBuffer(tx.rlp)) - st.equal(pt.getMessageToSign().toString('hex'), tx.hash) - st.equal('0x' + pt.serialize().toString('hex'), tx.rlp) + const pt = Transaction.fromSerializedTx(toBytes(tx.rlp)) + st.equal(bytesToHex(pt.getMessageToSign()), tx.hash) + st.equal(bytesToPrefixedHexString(pt.serialize()), tx.rlp) st.equal(pt.getSenderAddress().toString(), '0x' + tx.sender) } st.end() @@ -301,26 +301,25 @@ tape('[Transaction]', function (t) { '0x0de0b6b3a7640000', '0x', ] - const privateKey = Buffer.from( - '4646464646464646464646464646464646464646464646464646464646464646', - 'hex' + const privateKey = hexStringToBytes( + '4646464646464646464646464646464646464646464646464646464646464646' ) - const pt = Transaction.fromValuesArray(txRaw.map(toBuffer)) + const pt = Transaction.fromValuesArray(txRaw.map(toBytes)) // Note that Vitalik's example has a very similar value denoted "signing data". // It's not the output of `serialize()`, but the pre-image of the hash returned by `tx.hash(false)`. // We don't have a getter for such a value in Transaction. st.equal( - pt.serialize().toString('hex'), + bytesToHex(pt.serialize()), 'ec098504a817c800825208943535353535353535353535353535353535353535880de0b6b3a764000080808080' ) const signedTx = pt.sign(privateKey) st.equal( - signedTx.getMessageToSign().toString('hex'), + bytesToHex(signedTx.getMessageToSign()), 'daf5a779ae972f972197303d7b574746c7ef83eadac0f2791ad23db92e4c8e53' ) st.equal( - signedTx.serialize().toString('hex'), + bytesToHex(signedTx.serialize()), 'f86c098504a817c800825208943535353535353535353535353535353535353535880de0b6b3a76400008025a028ef61340bd939bc2195fe537567866003e1a15d3c71ff63e1590620aa636276a067cbe9d8997f761aecb703304b3800ccf555c9f3dc64214b297fb1966a3b6d83' ) st.end() @@ -332,11 +331,11 @@ tape('[Transaction]', function (t) { function (st) { const common = new Common({ chain: 1, hardfork: Hardfork.Petersburg }) for (const txData of txFixtures.slice(0, 3)) { - const tx = Transaction.fromValuesArray(txData.raw.slice(0, 6).map(toBuffer), { + const tx = Transaction.fromValuesArray(txData.raw.slice(0, 6).map(toBytes), { common, }) - const privKey = Buffer.from(txData.privateKey, 'hex') + const privKey = hexStringToBytes(txData.privateKey) const txSigned = tx.sign(privKey) st.equal( @@ -361,15 +360,14 @@ tape('[Transaction]', function (t) { '0x0de0b6b3a7640000', '0x', ] - const privateKey = Buffer.from( - 'DE3128752F183E8930D7F00A2AAA302DCB5E700B2CBA2D8CA5795660F07DEFD5', - 'hex' + const privateKey = hexStringToBytes( + 'DE3128752F183E8930D7F00A2AAA302DCB5E700B2CBA2D8CA5795660F07DEFD5' ) const common = new Common({ chain: 3 }) - const tx = Transaction.fromValuesArray(txRaw.map(toBuffer), { common }) + const tx = Transaction.fromValuesArray(txRaw.map(toBytes), { common }) const signedTx = tx.sign(privateKey) st.equal( - signedTx.serialize().toString('hex'), + bytesToHex(signedTx.serialize()), 'f86c018502540be40082520894d7250824390ec5c8b71d856b5de895e271170d9d880de0b6b3a76400008029a0d3512c68099d184ccf54f44d9d6905bff303128574b663dcf10b4c726ddd8133a0628acc8f481dea593f13309dfc5f0340f83fdd40cf9fbe47f782668f6f3aec74' ) @@ -389,9 +387,8 @@ tape('[Transaction]', function (t) { value: '0x0', } - const privateKey = Buffer.from( - '4646464646464646464646464646464646464646464646464646464646464646', - 'hex' + const privateKey = hexStringToBytes( + '4646464646464646464646464646464646464646464646464646464646464646' ) const common = new Common({ @@ -436,7 +433,7 @@ tape('[Transaction]', function (t) { st.true( signedWithoutEIP155.v?.toString(16) === '1c' || signedWithoutEIP155.v?.toString(16) === '1b', - "v shouldn' be EIP155 encoded" + "v shouldn't be EIP155 encoded" ) st.end() @@ -469,7 +466,7 @@ tape('[Transaction]', function (t) { let tx = Transaction.fromTxData({}, { common }) st.equal(tx.common.chainId(), BigInt(5)) - const privKey = Buffer.from(txFixtures[0].privateKey, 'hex') + const privKey = hexStringToBytes(txFixtures[0].privateKey) tx = tx.sign(privKey) const serialized = tx.serialize() @@ -484,7 +481,7 @@ tape('[Transaction]', function (t) { t.test('freeze property propagates from unsigned tx to signed tx', function (st) { const tx = Transaction.fromTxData({}, { freeze: false }) st.notOk(Object.isFrozen(tx), 'tx object is not frozen') - const privKey = Buffer.from(txFixtures[0].privateKey, 'hex') + const privKey = hexStringToBytes(txFixtures[0].privateKey) const signedTxn = tx.sign(privKey) st.notOk(Object.isFrozen(signedTxn), 'tx object is not frozen') st.end() @@ -492,7 +489,7 @@ tape('[Transaction]', function (t) { t.test('common propagates from the common of tx, not the common in TxOptions', function (st) { const common = new Common({ chain: Chain.Rinkeby, hardfork: Hardfork.London }) - const pkey = Buffer.from(txFixtures[0].privateKey, 'hex') + const pkey = hexStringToBytes(txFixtures[0].privateKey) const txn = Transaction.fromTxData({}, { common, freeze: false }) const newCommon = new Common({ chain: Chain.Rinkeby, hardfork: Hardfork.London, eips: [2537] }) st.notDeepEqual(newCommon, common, 'new common is different than original common') @@ -518,9 +515,8 @@ tape('[Transaction]', function (t) { to: '0xd9024df085d09398ec76fbed18cac0e1149f50dc', value: '0x0', } - const privateKey = Buffer.from( - '4646464646464646464646464646464646464646464646464646464646464646', - 'hex' + const privateKey = hexStringToBytes( + '4646464646464646464646464646464646464646464646464646464646464646' ) tx = Transaction.fromTxData(txData) st.notOk(tx.isSigned()) @@ -541,7 +537,7 @@ tape('[Transaction]', function (t) { tx = Transaction.fromSerializedTx(rawSigned) st.ok(tx.isSigned()) - const signedValues = arrToBufArr(RLP.decode(Uint8Array.from(rawSigned))) as Buffer[] + const signedValues = RLP.decode(Uint8Array.from(rawSigned)) as Uint8Array[] tx = Transaction.fromValuesArray(signedValues) st.ok(tx.isSigned()) tx = Transaction.fromValuesArray(signedValues.slice(0, 6)) diff --git a/packages/tx/test/testLoader.ts b/packages/tx/test/testLoader.ts index b5b4bd4e83..62bcaa6adf 100644 --- a/packages/tx/test/testLoader.ts +++ b/packages/tx/test/testLoader.ts @@ -1,3 +1,4 @@ +import { bytesToHex } from '@ethereumjs/util' import * as dir from 'node-dir' import * as path from 'path' @@ -38,7 +39,7 @@ export async function getTests( } const fileCallback = async ( err: Error | undefined, - content: string | Buffer, + content: string | Uint8Array, fileName: string, next: Function ) => { @@ -48,7 +49,7 @@ export async function getTests( } const subDir = fileName.substr(directory.length + 1) const parsedFileName = path.parse(fileName).name - content = Buffer.isBuffer(content) ? content.toString() : content + content = content instanceof Uint8Array ? bytesToHex(content) : content const testsByName = JSON.parse(content) const testNames = Object.keys(testsByName) for (const testName of testNames) { diff --git a/packages/tx/test/transactionFactory.spec.ts b/packages/tx/test/transactionFactory.spec.ts index 6354f658cd..2612a890a0 100644 --- a/packages/tx/test/transactionFactory.spec.ts +++ b/packages/tx/test/transactionFactory.spec.ts @@ -1,4 +1,5 @@ import { Chain, Common, Hardfork } from '@ethereumjs/common' +import { hexStringToBytes } from '@ethereumjs/util' import * as tape from 'tape' import { @@ -13,7 +14,7 @@ const common = new Common({ hardfork: Hardfork.London, }) -const pKey = Buffer.from('4646464646464646464646464646464646464646464646464646464646464646', 'hex') +const pKey = hexStringToBytes('4646464646464646464646464646464646464646464646464646464646464646') const unsignedTx = Transaction.fromTxData({}) const signedTx = unsignedTx.sign(pKey) @@ -89,11 +90,11 @@ tape('[TransactionFactory]: Basic functions', function (t) { t.test('fromBlockBodyData() -> success cases', function (st) { for (const txType of txTypes) { - let rawTx + let rawTx: Uint8Array | Uint8Array[] if (txType.eip2718) { - rawTx = txType.signed.serialize() as Buffer + rawTx = txType.signed.serialize() } else { - rawTx = txType.signed.raw() as Buffer[] + rawTx = txType.signed.raw() as Uint8Array[] } const tx = TransactionFactory.fromBlockBodyData(rawTx, { common }) st.equal(tx.constructor.name, txType.name, `should return the right type (${txType.name})`) diff --git a/packages/tx/test/transactionRunner.ts b/packages/tx/test/transactionRunner.ts index c19bf9bf59..8aff9bb76f 100644 --- a/packages/tx/test/transactionRunner.ts +++ b/packages/tx/test/transactionRunner.ts @@ -1,5 +1,5 @@ import { Common } from '@ethereumjs/common' -import { toBuffer } from '@ethereumjs/util' +import { bytesToHex, toBytes } from '@ethereumjs/util' import * as minimist from 'minimist' import * as tape from 'tape' @@ -62,7 +62,7 @@ tape('TransactionTests', async (t) => { const shouldBeInvalid = forkTestData.exception !== undefined try { - const rawTx = toBuffer(testData.txbytes) + const rawTx = toBytes(testData.txbytes) const hardfork = forkNameMap[forkName] const common = new Common({ chain: 1, hardfork }) const activateEIPs = EIPs[forkName] @@ -71,7 +71,7 @@ tape('TransactionTests', async (t) => { } const tx = TransactionFactory.fromSerializedData(rawTx, { common }) const sender = tx.getSenderAddress().toString() - const hash = tx.hash().toString('hex') + const hash = bytesToHex(tx.hash()) const txIsValid = tx.validate() const senderIsCorrect = forkTestData.sender === sender const hashIsCorrect = forkTestData.hash?.slice(2) === hash diff --git a/packages/tx/test/typedTxsAndEIP2930.spec.ts b/packages/tx/test/typedTxsAndEIP2930.spec.ts index 0dd06c4d1c..19e17fef98 100644 --- a/packages/tx/test/typedTxsAndEIP2930.spec.ts +++ b/packages/tx/test/typedTxsAndEIP2930.spec.ts @@ -4,17 +4,20 @@ import { MAX_INTEGER, MAX_UINT64, SECP256K1_ORDER_DIV_2, - bufferToBigInt, - bufferToHex, + bytesToBigInt, + bytesToPrefixedHexString, + concatBytes, + equalsBytes, + hexStringToBytes, privateToAddress, } from '@ethereumjs/util' import * as tape from 'tape' import { AccessListEIP2930Transaction, FeeMarketEIP1559Transaction } from '../src' -import type { AccessList, AccessListBufferItem } from '../src' +import type { AccessList, AccessListBytesItem } from '../src' -const pKey = Buffer.from('4646464646464646464646464646464646464646464646464646464646464646', 'hex') +const pKey = hexStringToBytes('4646464646464646464646464646464646464646464646464646464646464646') const address = privateToAddress(pKey) const common = new Common({ @@ -35,8 +38,8 @@ const txTypes = [ }, ] -const validAddress = Buffer.from('01'.repeat(20), 'hex') -const validSlot = Buffer.from('01'.repeat(32), 'hex') +const validAddress = hexStringToBytes('01'.repeat(20)) +const validSlot = hexStringToBytes('01'.repeat(32)) const chainId = BigInt(1) tape( @@ -132,7 +135,7 @@ tape( t.test('Initialization / Getter -> fromSerializedTx()', function (t) { for (const txType of txTypes) { try { - txType.class.fromSerializedTx(Buffer.from([99]), {}) + txType.class.fromSerializedTx(new Uint8Array([99]), {}) } catch (e: any) { t.ok( e.message.includes('wrong tx type'), @@ -142,7 +145,7 @@ tape( try { // Correct tx type + RLP-encoded 5 - const serialized = Buffer.concat([Buffer.from([txType.type]), Buffer.from([5])]) + const serialized = concatBytes(new Uint8Array([txType.type]), new Uint8Array([5])) txType.class.fromSerializedTx(serialized, {}) } catch (e: any) { t.ok( @@ -153,7 +156,7 @@ tape( try { // Correct tx type + RLP-encoded empty list - const serialized = Buffer.concat([Buffer.from([txType.type]), Buffer.from('c0', 'hex')]) + const serialized = concatBytes(new Uint8Array([txType.type]), hexStringToBytes('c0')) txType.class.fromSerializedTx(serialized, {}) } catch (e: any) { t.ok( @@ -169,8 +172,8 @@ tape( for (const txType of txTypes) { const access: AccessList = [ { - address: bufferToHex(validAddress), - storageKeys: [bufferToHex(validSlot)], + address: bytesToPrefixedHexString(validAddress), + storageKeys: [bytesToPrefixedHexString(validSlot)], }, ] const txn = txType.class.fromTxData( @@ -183,11 +186,11 @@ tape( // Check if everything is converted - const BufferArray = txn.accessList + const bytes = txn.accessList const JSON = txn.AccessListJSON - st.ok(BufferArray[0][0].equals(validAddress)) - st.ok(BufferArray[0][1][0].equals(validSlot)) + st.ok(equalsBytes(bytes[0][0], validAddress)) + st.ok(equalsBytes(bytes[0][1][0], validSlot)) st.deepEqual(JSON, access, `should allow json-typed access lists (${txType.name})`) @@ -195,7 +198,7 @@ tape( const txnRaw = txType.class.fromTxData( { - accessList: BufferArray, + accessList: bytes, chainId: 1, }, { common } @@ -212,7 +215,7 @@ tape( for (const txType of txTypes) { let accessList: any[] = [ [ - Buffer.from('01'.repeat(21), 'hex'), // Address of 21 bytes instead of 20 + hexStringToBytes('01'.repeat(21)), // Address of 21 bytes instead of 20 [], ], ] @@ -225,7 +228,7 @@ tape( [ validAddress, [ - Buffer.from('01'.repeat(31), 'hex'), // Slot of 31 bytes instead of 32 + hexStringToBytes('01'.repeat(31)), // Slot of 31 bytes instead of 32 ], ], ] @@ -265,7 +268,7 @@ tape( for (const txType of txTypes) { let tx = txType.class.fromTxData( { - data: Buffer.from('010200', 'hex'), + data: hexStringToBytes('010200'), to: validAddress, accessList: [[validAddress, [validSlot]]], chainId, @@ -274,7 +277,10 @@ tape( ) let signed = tx.sign(pKey) const signedAddress = signed.getSenderAddress() - t.ok(signedAddress.buf.equals(address), `should sign a transaction (${txType.name})`) + t.ok( + equalsBytes(signedAddress.bytes, address), + `should sign a transaction (${txType.name})` + ) signed.verifySignature() // If this throws, test will not end. tx = txType.class.fromTxData({}, { common }) @@ -333,13 +339,13 @@ tape('[AccessListEIP2930Transaction] -> Class Specific Tests', function (t) { 'should initialize correctly from its own data' ) - const validAddress = Buffer.from('01'.repeat(20), 'hex') - const validSlot = Buffer.from('01'.repeat(32), 'hex') + const validAddress = hexStringToBytes('01'.repeat(20)) + const validSlot = hexStringToBytes('01'.repeat(32)) const chainId = BigInt(1) try { AccessListEIP2930Transaction.fromTxData( { - data: Buffer.from('010200', 'hex'), + data: hexStringToBytes('010200'), to: validAddress, accessList: [[validAddress, [validSlot]]], chainId, @@ -358,12 +364,12 @@ tape('[AccessListEIP2930Transaction] -> Class Specific Tests', function (t) { }) t.throws(() => { - const buffer = Buffer.from([]) - const address = Buffer.from([]) - const storageKeys = [Buffer.from([]), Buffer.from([])] - const aclBuf: AccessListBufferItem = [address, storageKeys] + const bytes = new Uint8Array(0) + const address = new Uint8Array(0) + const storageKeys = [new Uint8Array(0), new Uint8Array(0)] + const aclBytes: AccessListBytesItem = [address, storageKeys] AccessListEIP2930Transaction.fromValuesArray( - [buffer, buffer, buffer, buffer, buffer, buffer, buffer, [aclBuf], buffer], + [bytes, bytes, bytes, bytes, bytes, bytes, bytes, [aclBytes], bytes], {} ) }, 'should throw with values array with length different than 8 or 11') @@ -371,7 +377,7 @@ tape('[AccessListEIP2930Transaction] -> Class Specific Tests', function (t) { t.test('should return right upfront cost', (st) => { let tx = AccessListEIP2930Transaction.fromTxData( { - data: Buffer.from('010200', 'hex'), + data: hexStringToBytes('010200'), to: validAddress, accessList: [[validAddress, [validSlot]]], chainId, @@ -403,7 +409,7 @@ tape('[AccessListEIP2930Transaction] -> Class Specific Tests', function (t) { // In this Tx, `to` is `undefined`, so we should charge homestead creation gas. tx = AccessListEIP2930Transaction.fromTxData( { - data: Buffer.from('010200', 'hex'), + data: hexStringToBytes('010200'), accessList: [[validAddress, [validSlot]]], chainId, }, @@ -458,22 +464,20 @@ tape('[AccessListEIP2930Transaction] -> Class Specific Tests', function (t) { t.test('unsigned tx -> getMessageToSign()', function (t) { const unsignedTx = AccessListEIP2930Transaction.fromTxData( { - data: Buffer.from('010200', 'hex'), + data: hexStringToBytes('010200'), to: validAddress, accessList: [[validAddress, [validSlot]]], chainId, }, { common } ) - const expectedHash = Buffer.from( - '78528e2724aa359c58c13e43a7c467eb721ce8d410c2a12ee62943a3aaefb60b', - 'hex' + const expectedHash = hexStringToBytes( + '78528e2724aa359c58c13e43a7c467eb721ce8d410c2a12ee62943a3aaefb60b' ) t.deepEqual(unsignedTx.getMessageToSign(true), expectedHash), 'correct hashed version' - const expectedSerialization = Buffer.from( - '01f858018080809401010101010101010101010101010101010101018083010200f838f7940101010101010101010101010101010101010101e1a00101010101010101010101010101010101010101010101010101010101010101', - 'hex' + const expectedSerialization = hexStringToBytes( + '01f858018080809401010101010101010101010101010101010101018083010200f838f7940101010101010101010101010101010101010101e1a00101010101010101010101010101010101010101010101010101010101010101' ) t.deepEqual( unsignedTx.getMessageToSign(false), @@ -488,19 +492,18 @@ tape('[AccessListEIP2930Transaction] -> Class Specific Tests', function (t) { // https://github.com/INFURA/go-ethlibs/blob/75b2a52a39d353ed8206cffaf68d09bd1b154aae/eth/transaction_signing_test.go#L87 t.test('should sign transaction correctly and return expected JSON', function (t) { - const address = Buffer.from('0000000000000000000000000000000000001337', 'hex') - const slot1 = Buffer.from( - '0000000000000000000000000000000000000000000000000000000000000000', - 'hex' + const address = hexStringToBytes('0000000000000000000000000000000000001337') + const slot1 = hexStringToBytes( + '0000000000000000000000000000000000000000000000000000000000000000' ) const txData = { - data: Buffer.from('', 'hex'), + data: hexStringToBytes(''), gasLimit: 0x62d4, gasPrice: 0x3b9aca00, nonce: 0x00, - to: new Address(Buffer.from('df0a88b2b68c673713a8ec826003676f272e3573', 'hex')), + to: new Address(hexStringToBytes('df0a88b2b68c673713a8ec826003676f272e3573')), value: 0x01, - chainId: bufferToBigInt(Buffer.from('796f6c6f763378', 'hex')), + chainId: bytesToBigInt(hexStringToBytes('796f6c6f763378')), accessList: [[address, [slot1]]], } @@ -515,43 +518,42 @@ tape('[AccessListEIP2930Transaction] -> Class Specific Tests', function (t) { }) usedCommon.setEIPs([2718, 2929, 2930]) - const expectedUnsignedRaw = Buffer.from( - '01f86587796f6c6f76337880843b9aca008262d494df0a88b2b68c673713a8ec826003676f272e35730180f838f7940000000000000000000000000000000000001337e1a00000000000000000000000000000000000000000000000000000000000000000808080', - 'hex' + const expectedUnsignedRaw = hexStringToBytes( + '01f86587796f6c6f76337880843b9aca008262d494df0a88b2b68c673713a8ec826003676f272e35730180f838f7940000000000000000000000000000000000001337e1a00000000000000000000000000000000000000000000000000000000000000000808080' ) - const pkey = Buffer.from( - 'fad9c8855b740a0b7ed4c221dbad0f33a83a49cad6b3fe8d5817ac83d38b6a19', - 'hex' + const pkey = hexStringToBytes( + 'fad9c8855b740a0b7ed4c221dbad0f33a83a49cad6b3fe8d5817ac83d38b6a19' ) - const expectedSigned = Buffer.from( - '01f8a587796f6c6f76337880843b9aca008262d494df0a88b2b68c673713a8ec826003676f272e35730180f838f7940000000000000000000000000000000000001337e1a0000000000000000000000000000000000000000000000000000000000000000080a0294ac94077b35057971e6b4b06dfdf55a6fbed819133a6c1d31e187f1bca938da00be950468ba1c25a5cb50e9f6d8aa13c8cd21f24ba909402775b262ac76d374d', - 'hex' + const expectedSigned = hexStringToBytes( + '01f8a587796f6c6f76337880843b9aca008262d494df0a88b2b68c673713a8ec826003676f272e35730180f838f7940000000000000000000000000000000000001337e1a0000000000000000000000000000000000000000000000000000000000000000080a0294ac94077b35057971e6b4b06dfdf55a6fbed819133a6c1d31e187f1bca938da00be950468ba1c25a5cb50e9f6d8aa13c8cd21f24ba909402775b262ac76d374d' ) - const expectedHash = Buffer.from( - 'bbd570a3c6acc9bb7da0d5c0322fe4ea2a300db80226f7df4fef39b2d6649eec', - 'hex' + const expectedHash = hexStringToBytes( + 'bbd570a3c6acc9bb7da0d5c0322fe4ea2a300db80226f7df4fef39b2d6649eec' ) const v = BigInt(0) - const r = bufferToBigInt( - Buffer.from('294ac94077b35057971e6b4b06dfdf55a6fbed819133a6c1d31e187f1bca938d', 'hex') + const r = bytesToBigInt( + hexStringToBytes('294ac94077b35057971e6b4b06dfdf55a6fbed819133a6c1d31e187f1bca938d') ) - const s = bufferToBigInt( - Buffer.from('0be950468ba1c25a5cb50e9f6d8aa13c8cd21f24ba909402775b262ac76d374d', 'hex') + const s = bytesToBigInt( + hexStringToBytes('0be950468ba1c25a5cb50e9f6d8aa13c8cd21f24ba909402775b262ac76d374d') ) const unsignedTx = AccessListEIP2930Transaction.fromTxData(txData, { common: usedCommon }) const serializedMessageRaw = unsignedTx.serialize() - t.ok(expectedUnsignedRaw.equals(serializedMessageRaw), 'serialized unsigned message correct') + t.ok( + equalsBytes(expectedUnsignedRaw, serializedMessageRaw), + 'serialized unsigned message correct' + ) const signed = unsignedTx.sign(pkey) t.ok(v === signed.v!, 'v correct') t.ok(r === signed.r!, 'r correct') t.ok(s === signed.s!, 's correct') - t.ok(expectedSigned.equals(signed.serialize()), 'serialized signed message correct') - t.ok(expectedHash.equals(signed.hash()), 'hash correct') + t.ok(equalsBytes(expectedSigned, signed.serialize()), 'serialized signed message correct') + t.ok(equalsBytes(expectedHash, signed.hash()), 'hash correct') const expectedJSON = { chainId: '0x796f6c6f763378', diff --git a/packages/util/src/account.ts b/packages/util/src/account.ts index d181f3df24..0e326c4a27 100644 --- a/packages/util/src/account.ts +++ b/packages/util/src/account.ts @@ -1,53 +1,57 @@ import { RLP } from '@ethereumjs/rlp' import { keccak256 } from 'ethereum-cryptography/keccak' import { Point, utils } from 'ethereum-cryptography/secp256k1' -import { bytesToHex } from 'ethereum-cryptography/utils' +import { + bytesToHex, + concatBytes, + equalsBytes, + hexToBytes, + utf8ToBytes, +} from 'ethereum-cryptography/utils' import { - arrToBufArr, - bigIntToUnpaddedBuffer, - bufArrToArr, - bufferToBigInt, - bufferToHex, - toBuffer, + bigIntToUnpaddedBytes, + bytesToBigInt, + bytesToPrefixedHexString, + toBytes, zeros, } from './bytes' import { KECCAK256_NULL, KECCAK256_RLP } from './constants' -import { assertIsBuffer, assertIsHexString, assertIsString } from './helpers' +import { assertIsBytes, assertIsHexString, assertIsString } from './helpers' import { stripHexPrefix } from './internal' -import type { BigIntLike, BufferLike } from './types' +import type { BigIntLike, BytesLike } from './types' const _0n = BigInt(0) export interface AccountData { nonce?: BigIntLike balance?: BigIntLike - storageRoot?: BufferLike - codeHash?: BufferLike + storageRoot?: BytesLike + codeHash?: BytesLike } -export type AccountBodyBuffer = [Buffer, Buffer, Buffer | Uint8Array, Buffer | Uint8Array] +export type AccountBodyBytes = [Uint8Array, Uint8Array, Uint8Array, Uint8Array] export class Account { nonce: bigint balance: bigint - storageRoot: Buffer - codeHash: Buffer + storageRoot: Uint8Array + codeHash: Uint8Array static fromAccountData(accountData: AccountData) { const { nonce, balance, storageRoot, codeHash } = accountData return new Account( - nonce !== undefined ? bufferToBigInt(toBuffer(nonce)) : undefined, - balance !== undefined ? bufferToBigInt(toBuffer(balance)) : undefined, - storageRoot !== undefined ? toBuffer(storageRoot) : undefined, - codeHash !== undefined ? toBuffer(codeHash) : undefined + nonce !== undefined ? bytesToBigInt(toBytes(nonce)) : undefined, + balance !== undefined ? bytesToBigInt(toBytes(balance)) : undefined, + storageRoot !== undefined ? toBytes(storageRoot) : undefined, + codeHash !== undefined ? toBytes(codeHash) : undefined ) } - public static fromRlpSerializedAccount(serialized: Buffer) { - const values = arrToBufArr(RLP.decode(Uint8Array.from(serialized)) as Uint8Array[]) as Buffer[] + public static fromRlpSerializedAccount(serialized: Uint8Array) { + const values = RLP.decode(serialized) as Uint8Array[] if (!Array.isArray(values)) { throw new Error('Invalid serialized account input. Must be array') @@ -56,10 +60,10 @@ export class Account { return this.fromValuesArray(values) } - public static fromValuesArray(values: Buffer[]) { + public static fromValuesArray(values: Uint8Array[]) { const [nonce, balance, storageRoot, codeHash] = values - return new Account(bufferToBigInt(nonce), bufferToBigInt(balance), storageRoot, codeHash) + return new Account(bytesToBigInt(nonce), bytesToBigInt(balance), storageRoot, codeHash) } /** @@ -91,29 +95,29 @@ export class Account { } /** - * Returns a Buffer Array of the raw Buffers for the account, in order. + * Returns an array of Uint8Arrays of the raw bytes for the account, in order. */ - raw(): Buffer[] { + raw(): Uint8Array[] { return [ - bigIntToUnpaddedBuffer(this.nonce), - bigIntToUnpaddedBuffer(this.balance), + bigIntToUnpaddedBytes(this.nonce), + bigIntToUnpaddedBytes(this.balance), this.storageRoot, this.codeHash, ] } /** - * Returns the RLP serialization of the account as a `Buffer`. + * Returns the RLP serialization of the account as a `Uint8Array`. */ - serialize(): Buffer { - return Buffer.from(RLP.encode(bufArrToArr(this.raw()))) + serialize(): Uint8Array { + return RLP.encode(this.raw()) } /** * Returns a `Boolean` determining if the account is a contract. */ isContract(): boolean { - return !this.codeHash.equals(KECCAK256_NULL) + return !equalsBytes(this.codeHash, KECCAK256_NULL) } /** @@ -122,7 +126,7 @@ export class Account { * "An account is considered empty when it has no code and zero nonce and zero balance." */ isEmpty(): boolean { - return this.balance === _0n && this.nonce === _0n && this.codeHash.equals(KECCAK256_NULL) + return this.balance === _0n && this.nonce === _0n && equalsBytes(this.codeHash, KECCAK256_NULL) } } @@ -160,12 +164,12 @@ export const toChecksumAddress = function ( let prefix = '' if (eip1191ChainId !== undefined) { - const chainId = bufferToBigInt(toBuffer(eip1191ChainId)) + const chainId = bytesToBigInt(toBytes(eip1191ChainId)) prefix = chainId.toString() + '0x' } - const buf = Buffer.from(prefix + address, 'utf8') - const hash = bytesToHex(keccak256(buf)) + const bytes = utf8ToBytes(prefix + address) + const hash = bytesToHex(keccak256(bytes)) let ret = '0x' for (let i = 0; i < address.length; i++) { @@ -196,18 +200,18 @@ export const isValidChecksumAddress = function ( * @param from The address which is creating this new address * @param nonce The nonce of the from account */ -export const generateAddress = function (from: Buffer, nonce: Buffer): Buffer { - assertIsBuffer(from) - assertIsBuffer(nonce) +export const generateAddress = function (from: Uint8Array, nonce: Uint8Array): Uint8Array { + assertIsBytes(from) + assertIsBytes(nonce) - if (bufferToBigInt(nonce) === BigInt(0)) { + if (bytesToBigInt(nonce) === BigInt(0)) { // in RLP we want to encode null in the case of zero nonce // read the RLP documentation for an answer if you dare - return Buffer.from(keccak256(RLP.encode(bufArrToArr([from, null] as any)))).slice(-20) + return keccak256(RLP.encode([from, Uint8Array.from([])])).subarray(-20) } // Only take the lower 160bits of the hash - return Buffer.from(keccak256(RLP.encode(bufArrToArr([from, nonce])))).slice(-20) + return keccak256(RLP.encode([from, nonce])).subarray(-20) } /** @@ -216,10 +220,14 @@ export const generateAddress = function (from: Buffer, nonce: Buffer): Buffer { * @param salt A salt * @param initCode The init code of the contract being created */ -export const generateAddress2 = function (from: Buffer, salt: Buffer, initCode: Buffer): Buffer { - assertIsBuffer(from) - assertIsBuffer(salt) - assertIsBuffer(initCode) +export const generateAddress2 = function ( + from: Uint8Array, + salt: Uint8Array, + initCode: Uint8Array +): Uint8Array { + assertIsBytes(from) + assertIsBytes(salt) + assertIsBytes(initCode) if (from.length !== 20) { throw new Error('Expected from to be of length 20') @@ -228,17 +236,15 @@ export const generateAddress2 = function (from: Buffer, salt: Buffer, initCode: throw new Error('Expected salt to be of length 32') } - const address = keccak256( - Buffer.concat([Buffer.from('ff', 'hex'), from, salt, keccak256(initCode)]) - ) + const address = keccak256(concatBytes(hexToBytes('ff'), from, salt, keccak256(initCode))) - return toBuffer(address).slice(-20) + return address.subarray(-20) } /** * Checks if the private key satisfies the rules of the curve secp256k1. */ -export const isValidPrivate = function (privateKey: Buffer): boolean { +export const isValidPrivate = function (privateKey: Uint8Array): boolean { return utils.isValidPrivateKey(privateKey) } @@ -248,13 +254,13 @@ export const isValidPrivate = function (privateKey: Buffer): boolean { * @param publicKey The two points of an uncompressed key, unless sanitize is enabled * @param sanitize Accept public keys in other formats */ -export const isValidPublic = function (publicKey: Buffer, sanitize: boolean = false): boolean { - assertIsBuffer(publicKey) +export const isValidPublic = function (publicKey: Uint8Array, sanitize: boolean = false): boolean { + assertIsBytes(publicKey) if (publicKey.length === 64) { // Convert to SEC1 for secp256k1 // Automatically checks whether point is on curve try { - Point.fromHex(Buffer.concat([Buffer.from([4]), publicKey])) + Point.fromHex(concatBytes(Uint8Array.from([4]), publicKey)) return true } catch (e) { return false @@ -279,16 +285,16 @@ export const isValidPublic = function (publicKey: Buffer, sanitize: boolean = fa * @param pubKey The two points of an uncompressed key, unless sanitize is enabled * @param sanitize Accept public keys in other formats */ -export const pubToAddress = function (pubKey: Buffer, sanitize: boolean = false): Buffer { - assertIsBuffer(pubKey) +export const pubToAddress = function (pubKey: Uint8Array, sanitize: boolean = false): Uint8Array { + assertIsBytes(pubKey) if (sanitize && pubKey.length !== 64) { - pubKey = Buffer.from(Point.fromHex(pubKey).toRawBytes(false).slice(1)) + pubKey = Point.fromHex(pubKey).toRawBytes(false).subarray(1) } if (pubKey.length !== 64) { throw new Error('Expected pubKey to be of length 64') } // Only take the lower 160bits of the hash - return Buffer.from(keccak256(pubKey)).slice(-20) + return keccak256(pubKey).subarray(-20) } export const publicToAddress = pubToAddress @@ -296,27 +302,27 @@ export const publicToAddress = pubToAddress * Returns the ethereum public key of a given private key. * @param privateKey A private key must be 256 bits wide */ -export const privateToPublic = function (privateKey: Buffer): Buffer { - assertIsBuffer(privateKey) +export const privateToPublic = function (privateKey: Uint8Array): Uint8Array { + assertIsBytes(privateKey) // skip the type flag and use the X, Y points - return Buffer.from(Point.fromPrivateKey(privateKey).toRawBytes(false).slice(1)) + return Point.fromPrivateKey(privateKey).toRawBytes(false).subarray(1) } /** * Returns the ethereum address of a given private key. * @param privateKey A private key must be 256 bits wide */ -export const privateToAddress = function (privateKey: Buffer): Buffer { +export const privateToAddress = function (privateKey: Uint8Array): Uint8Array { return publicToAddress(privateToPublic(privateKey)) } /** * Converts a public key to the Ethereum format. */ -export const importPublic = function (publicKey: Buffer): Buffer { - assertIsBuffer(publicKey) +export const importPublic = function (publicKey: Uint8Array): Uint8Array { + assertIsBytes(publicKey) if (publicKey.length !== 64) { - publicKey = Buffer.from(Point.fromHex(publicKey).toRawBytes(false).slice(1)) + publicKey = Point.fromHex(publicKey).toRawBytes(false).subarray(1) } return publicKey } @@ -327,7 +333,7 @@ export const importPublic = function (publicKey: Buffer): Buffer { export const zeroAddress = function (): string { const addressLength = 20 const addr = zeros(addressLength) - return bufferToHex(addr) + return bytesToPrefixedHexString(addr) } /** @@ -344,33 +350,33 @@ export const isZeroAddress = function (hexAddress: string): boolean { return zeroAddr === hexAddress } -export function accountBodyFromSlim(body: AccountBodyBuffer) { +export function accountBodyFromSlim(body: AccountBodyBytes) { const [nonce, balance, storageRoot, codeHash] = body return [ nonce, balance, - arrToBufArr(storageRoot).length === 0 ? KECCAK256_RLP : storageRoot, - arrToBufArr(codeHash).length === 0 ? KECCAK256_NULL : codeHash, + storageRoot.length === 0 ? KECCAK256_RLP : storageRoot, + codeHash.length === 0 ? KECCAK256_NULL : codeHash, ] } const emptyUint8Arr = new Uint8Array(0) -export function accountBodyToSlim(body: AccountBodyBuffer) { +export function accountBodyToSlim(body: AccountBodyBytes) { const [nonce, balance, storageRoot, codeHash] = body return [ nonce, balance, - arrToBufArr(storageRoot).equals(KECCAK256_RLP) ? emptyUint8Arr : storageRoot, - arrToBufArr(codeHash).equals(KECCAK256_NULL) ? emptyUint8Arr : codeHash, + equalsBytes(storageRoot, KECCAK256_RLP) ? emptyUint8Arr : storageRoot, + equalsBytes(codeHash, KECCAK256_NULL) ? emptyUint8Arr : codeHash, ] } /** * Converts a slim account (per snap protocol spec) to the RLP encoded version of the account - * @param body Array of 4 Buffer-like items to represent the account + * @param body Array of 4 Uint8Array-like items to represent the account * @returns RLP encoded version of the account */ -export function accountBodyToRLP(body: AccountBodyBuffer, couldBeSlim = true) { +export function accountBodyToRLP(body: AccountBodyBytes, couldBeSlim = true) { const accountBody = couldBeSlim ? accountBodyFromSlim(body) : body - return arrToBufArr(RLP.encode(accountBody)) + return RLP.encode(accountBody) } diff --git a/packages/util/src/address.ts b/packages/util/src/address.ts index eaa26c4222..2d65597a9e 100644 --- a/packages/util/src/address.ts +++ b/packages/util/src/address.ts @@ -1,3 +1,5 @@ +import { equalsBytes } from 'ethereum-cryptography/utils' + import { generateAddress, generateAddress2, @@ -5,19 +7,19 @@ import { privateToAddress, pubToAddress, } from './account' -import { bigIntToBuffer, bufferToBigInt, toBuffer, zeros } from './bytes' +import { bigIntToBytes, bytesToBigInt, bytesToPrefixedHexString, toBytes, zeros } from './bytes' /** * Handling and generating Ethereum addresses */ export class Address { - public readonly buf: Buffer + public readonly bytes: Uint8Array - constructor(buf: Buffer) { - if (buf.length !== 20) { + constructor(bytes: Uint8Array) { + if (bytes.length !== 20) { throw new Error('Invalid address length') } - this.buf = buf + this.bytes = bytes } /** @@ -35,31 +37,31 @@ export class Address { if (!isValidAddress(str)) { throw new Error('Invalid address') } - return new Address(toBuffer(str)) + return new Address(toBytes(str)) } /** * Returns an address for a given public key. * @param pubKey The two points of an uncompressed key */ - static fromPublicKey(pubKey: Buffer): Address { - if (!Buffer.isBuffer(pubKey)) { - throw new Error('Public key should be Buffer') + static fromPublicKey(pubKey: Uint8Array): Address { + if (!(pubKey instanceof Uint8Array)) { + throw new Error('Public key should be Uint8Array') } - const buf = pubToAddress(pubKey) - return new Address(buf) + const bytes = pubToAddress(pubKey) + return new Address(bytes) } /** * Returns an address for a given private key. * @param privateKey A private key must be 256 bits wide */ - static fromPrivateKey(privateKey: Buffer): Address { - if (!Buffer.isBuffer(privateKey)) { - throw new Error('Private key should be Buffer') + static fromPrivateKey(privateKey: Uint8Array): Address { + if (!(privateKey instanceof Uint8Array)) { + throw new Error('Private key should be Uint8Array') } - const buf = privateToAddress(privateKey) - return new Address(buf) + const bytes = privateToAddress(privateKey) + return new Address(bytes) } /** @@ -71,7 +73,7 @@ export class Address { if (typeof nonce !== 'bigint') { throw new Error('Expected nonce to be a bigint') } - return new Address(generateAddress(from.buf, bigIntToBuffer(nonce))) + return new Address(generateAddress(from.bytes, bigIntToBytes(nonce))) } /** @@ -80,21 +82,21 @@ export class Address { * @param salt A salt * @param initCode The init code of the contract being created */ - static generate2(from: Address, salt: Buffer, initCode: Buffer): Address { - if (!Buffer.isBuffer(salt)) { - throw new Error('Expected salt to be a Buffer') + static generate2(from: Address, salt: Uint8Array, initCode: Uint8Array): Address { + if (!(salt instanceof Uint8Array)) { + throw new Error('Expected salt to be a Uint8Array') } - if (!Buffer.isBuffer(initCode)) { - throw new Error('Expected initCode to be a Buffer') + if (!(initCode instanceof Uint8Array)) { + throw new Error('Expected initCode to be a Uint8Array') } - return new Address(generateAddress2(from.buf, salt, initCode)) + return new Address(generateAddress2(from.bytes, salt, initCode)) } /** * Is address equal to another. */ equals(address: Address): boolean { - return this.buf.equals(address.buf) + return equalsBytes(this.bytes, address.bytes) } /** @@ -109,7 +111,7 @@ export class Address { * by EIP-1352 */ isPrecompileOrSystemAddress(): boolean { - const address = bufferToBigInt(this.buf) + const address = bytesToBigInt(this.bytes) const rangeMin = BigInt(0) const rangeMax = BigInt('0xffff') return address >= rangeMin && address <= rangeMax @@ -119,13 +121,13 @@ export class Address { * Returns hex encoding of address. */ toString(): string { - return '0x' + this.buf.toString('hex') + return bytesToPrefixedHexString(this.bytes) } /** - * Returns Buffer representation of address. + * Returns a new Uint8Array representation of address. */ - toBuffer(): Buffer { - return Buffer.from(this.buf) + toBytes(): Uint8Array { + return new Uint8Array(this.bytes) } } diff --git a/packages/util/src/bytes.ts b/packages/util/src/bytes.ts index 086295f419..e276b85b95 100644 --- a/packages/util/src/bytes.ts +++ b/packages/util/src/bytes.ts @@ -1,13 +1,47 @@ -import { assertIsArray, assertIsBuffer, assertIsHexString } from './helpers' +import { getRandomBytesSync } from 'ethereum-cryptography/random' +import { bytesToHex, bytesToUtf8, hexToBytes } from 'ethereum-cryptography/utils' + +import { assertIsArray, assertIsBytes, assertIsHexString } from './helpers' import { isHexPrefixed, isHexString, padToEven, stripHexPrefix } from './internal' -import type { - NestedBufferArray, - NestedUint8Array, - PrefixedHexString, - TransformableToArray, - TransformableToBuffer, -} from './types' +import type { PrefixedHexString, TransformabletoBytes } from './types' + +/**************** Borrowed from @chainsafe/ssz */ +// Caching this info costs about ~1000 bytes and speeds up toHexString() by x6 +const hexByByte = Array.from({ length: 256 }, (v, i) => i.toString(16).padStart(2, '0')) + +export const bytesToPrefixedHexString = (bytes: Uint8Array): string => { + let hex = '0x' + if (bytes === undefined || bytes.length === 0) return hex + for (const byte of bytes) { + hex += hexByByte[byte] + } + return hex +} + +export const hexStringToBytes = (hex: string): Uint8Array => { + if (typeof hex !== 'string') { + throw new Error(`hex argument type ${typeof hex} must be of type string`) + } + + if (hex.startsWith('0x')) { + hex = hex.slice(2) + } + + if (hex.length % 2 !== 0) { + hex = padToEven(hex) + } + + const byteLen = hex.length / 2 + const bytes = new Uint8Array(byteLen) + for (let i = 0; i < byteLen; i++) { + const byte = parseInt(hex.slice(i * 2, (i + 1) * 2), 16) + bytes[i] = byte + } + return bytes +} + +/******************************************/ /** * Converts a `Number` into a hex `String` @@ -26,74 +60,71 @@ export const intToHex = function (i: number) { * @param {Number} i * @return {Buffer} */ -export const intToBuffer = function (i: number) { +export const intToBytes = function (i: number) { const hex = intToHex(i) - return Buffer.from(padToEven(hex.slice(2)), 'hex') + return hexToBytes(padToEven(hex.slice(2))) } /** * Returns a buffer filled with 0s. * @param bytes the number of bytes the buffer should be */ -export const zeros = function (bytes: number): Buffer { - return Buffer.allocUnsafe(bytes).fill(0) +export const zeros = function (bytes: number): Uint8Array { + return new Uint8Array(bytes) } /** - * Pads a `Buffer` with zeros till it has `length` bytes. + * Pads a `Uint8Array` with zeros till it has `length` bytes. * Truncates the beginning or end of input if its length exceeds `length`. - * @param msg the value to pad (Buffer) + * @param msg the value to pad (Uint8Array) * @param length the number of bytes the output should be * @param right whether to start padding form the left or right * @return (Buffer) */ -const setLength = function (msg: Buffer, length: number, right: boolean) { - const buf = zeros(length) +const setLength = function (msg: Uint8Array, length: number, right: boolean) { if (right) { if (msg.length < length) { - msg.copy(buf) - return buf + return new Uint8Array([...msg, ...zeros(length - msg.length)]) } - return msg.slice(0, length) + return msg.subarray(0, length) } else { if (msg.length < length) { - msg.copy(buf, length - msg.length) - return buf + return new Uint8Array([...zeros(length - msg.length), ...msg]) } - return msg.slice(-length) + return msg.subarray(-length) } } /** - * Left Pads a `Buffer` with leading zeros till it has `length` bytes. + * Left Pads a `Uint8Array` with leading zeros till it has `length` bytes. * Or it truncates the beginning if it exceeds. * @param msg the value to pad (Buffer) * @param length the number of bytes the output should be - * @return (Buffer) + * @return (Uint8Array) */ -export const setLengthLeft = function (msg: Buffer, length: number) { - assertIsBuffer(msg) +export const setLengthLeft = function (msg: Uint8Array, length: number) { + assertIsBytes(msg) return setLength(msg, length, false) } /** - * Right Pads a `Buffer` with trailing zeros till it has `length` bytes. + * Right Pads a `Uint8Array` with trailing zeros till it has `length` bytes. * it truncates the end if it exceeds. - * @param msg the value to pad (Buffer) + * @param msg the value to pad (Uint8Array) * @param length the number of bytes the output should be - * @return (Buffer) + * @return (Uint8Array) */ -export const setLengthRight = function (msg: Buffer, length: number) { - assertIsBuffer(msg) +export const setLengthRight = function (msg: Uint8Array, length: number) { + assertIsBytes(msg) return setLength(msg, length, true) } /** - * Trims leading zeros from a `Buffer`, `String` or `Number[]`. - * @param a (Buffer|Array|String) - * @return (Buffer|Array|String) + * Trims leading zeros from a `Uint8Array`, `String` or `Number[]`. + * @param a (Uint8Array|Array|String) + * @return (Uint8Array|Array|String) */ -const stripZeros = function (a: any): Buffer | number[] | string { +const stripZeros = function (a: any): Uint8Array | number[] | string { let first = a[0] while (a.length > 0 && first.toString() === '0') { a = a.slice(1) @@ -103,13 +134,13 @@ const stripZeros = function (a: any): Buffer | number[] | string { } /** - * Trims leading zeros from a `Buffer`. - * @param a (Buffer) - * @return (Buffer) + * Trims leading zeros from a `Uint8Array`. + * @param a (Uint8Array) + * @return (Uint8Array) */ -export const unpadBuffer = function (a: Buffer): Buffer { - assertIsBuffer(a) - return stripZeros(a) as Buffer +export const unpadBytes = function (a: Uint8Array): Uint8Array { + assertIsBytes(a) + return stripZeros(a) as Uint8Array } /** @@ -133,85 +164,71 @@ export const unpadHexString = function (a: string): string { return ('0x' + stripZeros(a)) as string } -export type ToBufferInputTypes = +export type ToBytesInputTypes = | PrefixedHexString | number | bigint - | Buffer | Uint8Array | number[] - | TransformableToArray - | TransformableToBuffer + | TransformabletoBytes | null | undefined /** - * Attempts to turn a value into a `Buffer`. - * Inputs supported: `Buffer`, `String` (hex-prefixed), `Number`, null/undefined, `BigInt` and other objects - * with a `toArray()` or `toBuffer()` method. + * Attempts to turn a value into a `Uint8Array`. + * Inputs supported: `Buffer`, `Uint8Array`, `String` (hex-prefixed), `Number`, null/undefined, `BigInt` and other objects + * with a `toArray()` or `toBytes()` method. * @param v the value */ -export const toBuffer = function (v: ToBufferInputTypes): Buffer { + +export const toBytes = function (v: ToBytesInputTypes): Uint8Array { if (v === null || v === undefined) { - return Buffer.allocUnsafe(0) + return new Uint8Array() } if (Buffer.isBuffer(v)) { - return Buffer.from(v) + return Uint8Array.from(v) } if (Array.isArray(v) || v instanceof Uint8Array) { - return Buffer.from(v as Uint8Array) + return Uint8Array.from(v) } if (typeof v === 'string') { if (!isHexString(v)) { throw new Error( - `Cannot convert string to buffer. toBuffer only supports 0x-prefixed hex strings and this string was given: ${v}` + `Cannot convert string to Uint8Array. toBytes only supports 0x-prefixed hex strings and this string was given: ${v}` ) } - return Buffer.from(padToEven(stripHexPrefix(v)), 'hex') + return hexToBytes(padToEven(v.slice(2))) } if (typeof v === 'number') { - return intToBuffer(v) + return intToBytes(v) } if (typeof v === 'bigint') { if (v < BigInt(0)) { - throw new Error(`Cannot convert negative bigint to buffer. Given: ${v}`) + throw new Error(`Cannot convert negative bigint to Uint8Array. Given: ${v}`) } let n = v.toString(16) if (n.length % 2) n = '0' + n - return Buffer.from(n, 'hex') - } - - if (v.toArray) { - // converts a BN to a Buffer - return Buffer.from(v.toArray()) + return hexToBytes(n) } - if (v.toBuffer) { - return Buffer.from(v.toBuffer()) + if (v.toBytes !== undefined) { + // converts a `TransformableToBytes` object to a Uint8Array + return v.toBytes() } throw new Error('invalid type') } /** - * Converts a `Buffer` into a `0x`-prefixed hex `String`. - * @param buf `Buffer` object to convert - */ -export const bufferToHex = function (buf: Buffer): string { - buf = toBuffer(buf) - return '0x' + buf.toString('hex') -} - -/** - * Converts a {@link Buffer} to a {@link bigint} + * Converts a {@link Uint8Array} to a {@link bigint} */ -export function bufferToBigInt(buf: Buffer) { - const hex = bufferToHex(buf) +export function bytesToBigInt(bytes: Uint8Array) { + const hex = bytesToPrefixedHexString(bytes) if (hex === '0x') { return BigInt(0) } @@ -219,37 +236,37 @@ export function bufferToBigInt(buf: Buffer) { } /** - * Converts a {@link bigint} to a {@link Buffer} + * Converts a {@link bigint} to a {@link Uint8Array} */ -export function bigIntToBuffer(num: bigint) { - return toBuffer('0x' + num.toString(16)) +export const bigIntToBytes = (num: bigint) => { + return toBytes('0x' + padToEven(num.toString(16))) } /** - * Converts a `Buffer` to a `Number`. - * @param buf `Buffer` object to convert + * Converts a `Uint8Array` to a `Number`. + * @param bytes `Uint8Array` object to convert * @throws If the input number exceeds 53 bits. */ -export const bufferToInt = function (buf: Buffer): number { - const res = Number(bufferToBigInt(buf)) +export const bytesToInt = function (bytes: Uint8Array): number { + const res = Number(bytesToBigInt(bytes)) if (!Number.isSafeInteger(res)) throw new Error('Number exceeds 53 bits') return res } /** - * Interprets a `Buffer` as a signed integer and returns a `BigInt`. Assumes 256-bit numbers. + * Interprets a `Uint8Array` as a signed integer and returns a `BigInt`. Assumes 256-bit numbers. * @param num Signed integer value */ -export const fromSigned = function (num: Buffer): bigint { - return BigInt.asIntN(256, bufferToBigInt(num)) +export const fromSigned = function (num: Uint8Array): bigint { + return BigInt.asIntN(256, bytesToBigInt(num)) } /** - * Converts a `BigInt` to an unsigned integer and returns it as a `Buffer`. Assumes 256-bit numbers. + * Converts a `BigInt` to an unsigned integer and returns it as a `Uint8Array`. Assumes 256-bit numbers. * @param num */ -export const toUnsigned = function (num: bigint): Buffer { - return bigIntToBuffer(BigInt.asUintN(256, num)) +export const toUnsigned = function (num: bigint): Uint8Array { + return bigIntToBytes(BigInt.asUintN(256, num)) } /** @@ -264,19 +281,19 @@ export const addHexPrefix = function (str: string): string { } /** - * Shortens a string or buffer's hex string representation to maxLength (default 50). + * Shortens a string or Uint8Array's hex string representation to maxLength (default 50). * * Examples: * * Input: '657468657265756d000000000000000000000000000000000000000000000000' * Output: '657468657265756d0000000000000000000000000000000000…' */ -export function short(buffer: Buffer | string, maxLength: number = 50): string { - const bufferStr = Buffer.isBuffer(buffer) ? buffer.toString('hex') : buffer - if (bufferStr.length <= maxLength) { - return bufferStr +export function short(bytes: Uint8Array | string, maxLength: number = 50): string { + const byteStr = bytes instanceof Uint8Array ? bytesToHex(bytes) : bytes + if (byteStr.length <= maxLength) { + return byteStr } - return bufferStr.slice(0, maxLength) + '…' + return byteStr.slice(0, maxLength) + '…' } /** @@ -302,30 +319,13 @@ export const toUtf8 = function (hex: string): string { if (hex.length % 2 !== 0) { throw new Error('Invalid non-even hex string input for toUtf8() provided') } - const bufferVal = Buffer.from(hex.replace(zerosRegexp, ''), 'hex') - - return bufferVal.toString('utf8') -} + const bytesVal = hexToBytes(hex.replace(zerosRegexp, '')) -/** - * Converts a `Buffer` or `Array` to JSON. - * @param ba (Buffer|Array) - * @return (Array|String|null) - */ -export const baToJSON = function (ba: any): any { - if (Buffer.isBuffer(ba)) { - return `0x${ba.toString('hex')}` - } else if (ba instanceof Array) { - const array = [] - for (let i = 0; i < ba.length; i++) { - array.push(baToJSON(ba[i])) - } - return array - } + return bytesToUtf8(bytesVal) } /** - * Checks provided Buffers for leading zeroes and throws if found. + * Checks provided Uint8Array for leading zeroes and throws if found. * * Examples: * @@ -337,56 +337,85 @@ export const baToJSON = function (ba: any): any { * @param values An object containing string keys and Buffer values * @throws if any provided value is found to have leading zero bytes */ -export const validateNoLeadingZeroes = function (values: { [key: string]: Buffer | undefined }) { +export const validateNoLeadingZeroes = function (values: { + [key: string]: Uint8Array | undefined +}) { for (const [k, v] of Object.entries(values)) { if (v !== undefined && v.length > 0 && v[0] === 0) { - throw new Error(`${k} cannot have leading zeroes, received: ${v.toString('hex')}`) + throw new Error(`${k} cannot have leading zeroes, received: ${bytesToHex(v)}`) } } } /** - * Converts a {@link Uint8Array} or {@link NestedUint8Array} to {@link Buffer} or {@link NestedBufferArray} + * Converts a {@link bigint} to a `0x` prefixed hex string */ -export function arrToBufArr(arr: Uint8Array): Buffer -export function arrToBufArr(arr: NestedUint8Array): NestedBufferArray -export function arrToBufArr(arr: Uint8Array | NestedUint8Array): Buffer | NestedBufferArray -export function arrToBufArr(arr: Uint8Array | NestedUint8Array): Buffer | NestedBufferArray { - if (!Array.isArray(arr)) { - return Buffer.from(arr) - } - return arr.map((a) => arrToBufArr(a)) +export const bigIntToHex = (num: bigint) => { + return '0x' + num.toString(16) } /** - * Converts a {@link Buffer} or {@link NestedBufferArray} to {@link Uint8Array} or {@link NestedUint8Array} + * Convert value from bigint to an unpadded Uint8Array + * (useful for RLP transport) + * @param value value to convert */ -export function bufArrToArr(arr: Buffer): Uint8Array -export function bufArrToArr(arr: NestedBufferArray): NestedUint8Array -export function bufArrToArr(arr: Buffer | NestedBufferArray): Uint8Array | NestedUint8Array -export function bufArrToArr(arr: Buffer | NestedBufferArray): Uint8Array | NestedUint8Array { - if (!Array.isArray(arr)) { - return Uint8Array.from(arr ?? []) - } - return arr.map((a) => bufArrToArr(a)) +export function bigIntToUnpaddedBytes(value: bigint): Uint8Array { + return unpadBytes(bigIntToBytes(value)) +} + +export function intToUnpaddedBytes(value: number): Uint8Array { + return unpadBytes(intToBytes(value)) } /** - * Converts a {@link bigint} to a `0x` prefixed hex string + * Compares two Uint8Arrays and returns a number indicating their order in a sorted array. + * + * @param {Uint8Array} value1 - The first Uint8Array to compare. + * @param {Uint8Array} value2 - The second Uint8Array to compare. + * @returns {number} A positive number if value1 is larger than value2, + * A negative number if value1 is smaller than value2, + * or 0 if value1 and value2 are equal. */ -export const bigIntToHex = (num: bigint) => { - return '0x' + num.toString(16) +export function compareBytes(value1: Uint8Array, value2: Uint8Array): number { + const bigIntValue1 = bytesToBigInt(value1) + const bigIntValue2 = bytesToBigInt(value2) + return bigIntValue1 > bigIntValue2 ? 1 : bigIntValue1 < bigIntValue2 ? -1 : 0 } /** - * Convert value from bigint to an unpadded Buffer - * (useful for RLP transport) - * @param value value to convert + * Generates a Uint8Array of random bytes of specified length. + * + * @param {number} length - The length of the Uint8Array. + * @returns {Uint8Array} A Uint8Array of random bytes of specified length. */ -export function bigIntToUnpaddedBuffer(value: bigint): Buffer { - return unpadBuffer(bigIntToBuffer(value)) +export function randomBytes(length: number): Uint8Array { + return getRandomBytesSync(length) } -export function intToUnpaddedBuffer(value: number): Buffer { - return unpadBuffer(intToBuffer(value)) +/** + * This mirrors the functionality of the `ethereum-cryptography` export except + * it skips the check to validate that every element of `arrays` is indead a `uint8Array` + * Can give small performance gains on large arrays + * @param arrays an array of Uint8Arrays + * @returns one Uint8Array with all the elements of the original set + * works like `Buffer.concat` + */ +export const concatBytesNoTypeCheck = (...arrays: Uint8Array[]) => { + if (arrays.length === 1) return arrays[0] + const length = arrays.reduce((a, arr) => a + arr.length, 0) + const result = new Uint8Array(length) + for (let i = 0, pad = 0; i < arrays.length; i++) { + const arr = arrays[i] + result.set(arr, pad) + pad += arr.length + } + return result } + +export { + bytesToHex, + bytesToUtf8, + concatBytes, + equalsBytes, + utf8ToBytes, +} from 'ethereum-cryptography/utils' diff --git a/packages/util/src/constants.ts b/packages/util/src/constants.ts index 6b3d660217..5c2b174c1e 100644 --- a/packages/util/src/constants.ts +++ b/packages/util/src/constants.ts @@ -1,5 +1,5 @@ -import { Buffer } from 'buffer' import { CURVE } from 'ethereum-cryptography/secp256k1' +import { hexToBytes } from 'ethereum-cryptography/utils' /** * 2^64-1 @@ -40,7 +40,7 @@ export const KECCAK256_NULL_S = 'c5d2460186f7233c927e7db2dcc703c0e500b653ca82273 /** * Keccak-256 hash of null */ -export const KECCAK256_NULL = Buffer.from(KECCAK256_NULL_S, 'hex') +export const KECCAK256_NULL = hexToBytes(KECCAK256_NULL_S) /** * Keccak-256 of an RLP of an empty array @@ -51,7 +51,7 @@ export const KECCAK256_RLP_ARRAY_S = /** * Keccak-256 of an RLP of an empty array */ -export const KECCAK256_RLP_ARRAY = Buffer.from(KECCAK256_RLP_ARRAY_S, 'hex') +export const KECCAK256_RLP_ARRAY = hexToBytes(KECCAK256_RLP_ARRAY_S) /** * Keccak-256 hash of the RLP of null @@ -61,11 +61,11 @@ export const KECCAK256_RLP_S = '56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc0 /** * Keccak-256 hash of the RLP of null */ -export const KECCAK256_RLP = Buffer.from(KECCAK256_RLP_S, 'hex') +export const KECCAK256_RLP = hexToBytes(KECCAK256_RLP_S) /** * RLP encoded empty string */ -export const RLP_EMPTY_STRING = Buffer.from([0x80]) +export const RLP_EMPTY_STRING = Uint8Array.from([0x80]) export const MAX_WITHDRAWALS_PER_PAYLOAD = 16 diff --git a/packages/util/src/helpers.ts b/packages/util/src/helpers.ts index 297dbb0f8c..284018e788 100644 --- a/packages/util/src/helpers.ts +++ b/packages/util/src/helpers.ts @@ -15,9 +15,9 @@ export const assertIsHexString = function (input: string): void { * Throws if input is not a buffer * @param {Buffer} input value to check */ -export const assertIsBuffer = function (input: Buffer): void { - if (!Buffer.isBuffer(input)) { - const msg = `This method only supports Buffer but input was: ${input}` +export const assertIsBytes = function (input: Uint8Array): void { + if (!(input instanceof Uint8Array)) { + const msg = `This method only supports Uint8Array but input was: ${input}` throw new Error(msg) } } diff --git a/packages/util/src/index.ts b/packages/util/src/index.ts index f78bda10cf..df57cde654 100644 --- a/packages/util/src/index.ts +++ b/packages/util/src/index.ts @@ -29,7 +29,7 @@ export * from './withdrawal' export * from './signature' /** - * Utilities for manipulating Buffers, byte arrays, etc. + * Utilities for manipulating bytes, Uint8Arrays, etc. */ export * from './bytes' diff --git a/packages/util/src/internal.ts b/packages/util/src/internal.ts index 9a9d04ad1c..e55c58a33d 100644 --- a/packages/util/src/internal.ts +++ b/packages/util/src/internal.ts @@ -22,6 +22,8 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE */ +import { bytesToHex, utf8ToBytes } from 'ethereum-cryptography/utils' + /** * Returns a `Boolean` on whether or not the a `String` starts with '0x' * @param str the string input value @@ -75,7 +77,7 @@ export function getBinarySize(str: string) { throw new Error(`[getBinarySize] method requires input type 'string', received ${typeof str}`) } - return Buffer.byteLength(str, 'utf8') + return utf8ToBytes(str).byteLength } /** @@ -134,9 +136,9 @@ export function toAscii(hex: string): string { * @returns hex representation of input string */ export function fromUtf8(stringValue: string) { - const str = Buffer.from(stringValue, 'utf8') + const str = utf8ToBytes(stringValue) - return `0x${padToEven(str.toString('hex')).replace(/^0+|0+$/g, '')}` + return `0x${padToEven(bytesToHex(str)).replace(/^0+|0+$/g, '')}` } /** diff --git a/packages/util/src/signature.ts b/packages/util/src/signature.ts index 6294b1656a..6ee44a1075 100644 --- a/packages/util/src/signature.ts +++ b/packages/util/src/signature.ts @@ -1,14 +1,21 @@ import { keccak256 } from 'ethereum-cryptography/keccak' import { recoverPublicKey, signSync } from 'ethereum-cryptography/secp256k1' - -import { bufferToBigInt, bufferToHex, bufferToInt, setLengthLeft, toBuffer } from './bytes' +import { concatBytes, utf8ToBytes } from 'ethereum-cryptography/utils' + +import { + bytesToBigInt, + bytesToInt, + bytesToPrefixedHexString, + setLengthLeft, + toBytes, +} from './bytes' import { SECP256K1_ORDER, SECP256K1_ORDER_DIV_2 } from './constants' -import { assertIsBuffer } from './helpers' +import { assertIsBytes } from './helpers' export interface ECDSASignature { v: bigint - r: Buffer - s: Buffer + r: Uint8Array + s: Uint8Array } /** @@ -17,11 +24,15 @@ export interface ECDSASignature { * If `chainId` is provided assume an EIP-155-style signature and calculate the `v` value * accordingly, otherwise return a "static" `v` just derived from the `recovery` bit */ -export function ecsign(msgHash: Buffer, privateKey: Buffer, chainId?: bigint): ECDSASignature { +export function ecsign( + msgHash: Uint8Array, + privateKey: Uint8Array, + chainId?: bigint +): ECDSASignature { const [signature, recovery] = signSync(msgHash, privateKey, { recovered: true, der: false }) - const r = Buffer.from(signature.slice(0, 32)) - const s = Buffer.from(signature.slice(32, 64)) + const r = signature.subarray(0, 32) + const s = signature.subarray(32, 64) const v = chainId === undefined @@ -50,20 +61,20 @@ function isValidSigRecovery(recovery: bigint): boolean { * @returns Recovered public key */ export const ecrecover = function ( - msgHash: Buffer, + msgHash: Uint8Array, v: bigint, - r: Buffer, - s: Buffer, + r: Uint8Array, + s: Uint8Array, chainId?: bigint -): Buffer { - const signature = Buffer.concat([setLengthLeft(r, 32), setLengthLeft(s, 32)], 64) +): Uint8Array { + const signature = concatBytes(setLengthLeft(r, 32), setLengthLeft(s, 32)) const recovery = calculateSigRecovery(v, chainId) if (!isValidSigRecovery(recovery)) { throw new Error('Invalid signature v value') } const senderPubKey = recoverPublicKey(msgHash, signature, Number(recovery)) - return Buffer.from(senderPubKey.slice(1)) + return senderPubKey.subarray(1) } /** @@ -71,14 +82,22 @@ export const ecrecover = function ( * NOTE: Accepts `v === 0 | v === 1` for EIP1559 transactions * @returns Signature */ -export const toRpcSig = function (v: bigint, r: Buffer, s: Buffer, chainId?: bigint): string { +export const toRpcSig = function ( + v: bigint, + r: Uint8Array, + s: Uint8Array, + chainId?: bigint +): string { const recovery = calculateSigRecovery(v, chainId) if (!isValidSigRecovery(recovery)) { throw new Error('Invalid signature v value') } // geth (and the RPC eth_sign method) uses the 65 byte format used by Bitcoin - return bufferToHex(Buffer.concat([setLengthLeft(r, 32), setLengthLeft(s, 32), toBuffer(v)])) + + return bytesToPrefixedHexString( + concatBytes(setLengthLeft(r, 32), setLengthLeft(s, 32), toBytes(v)) + ) } /** @@ -86,19 +105,23 @@ export const toRpcSig = function (v: bigint, r: Buffer, s: Buffer, chainId?: big * NOTE: Accepts `v === 0 | v === 1` for EIP1559 transactions * @returns Signature */ -export const toCompactSig = function (v: bigint, r: Buffer, s: Buffer, chainId?: bigint): string { +export const toCompactSig = function ( + v: bigint, + r: Uint8Array, + s: Uint8Array, + chainId?: bigint +): string { const recovery = calculateSigRecovery(v, chainId) if (!isValidSigRecovery(recovery)) { throw new Error('Invalid signature v value') } - let ss = s + const ss = Uint8Array.from([...s]) if ((v > BigInt(28) && v % BigInt(2) === BigInt(1)) || v === BigInt(1) || v === BigInt(28)) { - ss = Buffer.from(s) ss[0] |= 0x80 } - return bufferToHex(Buffer.concat([setLengthLeft(r, 32), setLengthLeft(ss, 32)])) + return bytesToPrefixedHexString(concatBytes(setLengthLeft(r, 32), setLengthLeft(ss, 32))) } /** @@ -110,20 +133,20 @@ export const toCompactSig = function (v: bigint, r: Buffer, s: Buffer, chainId?: * it's a signed message (EIP-191 or EIP-712) adding `27` at the end. Remove if needed. */ export const fromRpcSig = function (sig: string): ECDSASignature { - const buf: Buffer = toBuffer(sig) + const bytes: Uint8Array = toBytes(sig) - let r: Buffer - let s: Buffer + let r: Uint8Array + let s: Uint8Array let v: bigint - if (buf.length >= 65) { - r = buf.slice(0, 32) - s = buf.slice(32, 64) - v = bufferToBigInt(buf.slice(64)) - } else if (buf.length === 64) { + if (bytes.length >= 65) { + r = bytes.subarray(0, 32) + s = bytes.subarray(32, 64) + v = bytesToBigInt(bytes.subarray(64)) + } else if (bytes.length === 64) { // Compact Signature Representation (https://eips.ethereum.org/EIPS/eip-2098) - r = buf.slice(0, 32) - s = buf.slice(32, 64) - v = BigInt(bufferToInt(buf.slice(32, 33)) >> 7) + r = bytes.subarray(0, 32) + s = bytes.subarray(32, 64) + v = BigInt(bytesToInt(bytes.subarray(32, 33)) >> 7) s[0] &= 0x7f } else { throw new Error('Invalid signature length') @@ -148,8 +171,8 @@ export const fromRpcSig = function (sig: string): ECDSASignature { */ export const isValidSignature = function ( v: bigint, - r: Buffer, - s: Buffer, + r: Uint8Array, + s: Uint8Array, homesteadOrLater: boolean = true, chainId?: bigint ): boolean { @@ -161,8 +184,8 @@ export const isValidSignature = function ( return false } - const rBigInt = bufferToBigInt(r) - const sBigInt = bufferToBigInt(s) + const rBigInt = bytesToBigInt(r) + const sBigInt = bytesToBigInt(s) if ( rBigInt === BigInt(0) || @@ -186,8 +209,8 @@ export const isValidSignature = function ( * call for a given `message`, or fed to `ecrecover` along with a signature to recover the public key * used to produce the signature. */ -export const hashPersonalMessage = function (message: Buffer): Buffer { - assertIsBuffer(message) - const prefix = Buffer.from(`\u0019Ethereum Signed Message:\n${message.length}`, 'utf-8') - return Buffer.from(keccak256(Buffer.concat([prefix, message]))) +export const hashPersonalMessage = function (message: Uint8Array): Uint8Array { + assertIsBytes(message) + const prefix = utf8ToBytes(`\u0019Ethereum Signed Message:\n${message.length}`) + return keccak256(concatBytes(prefix, message)) } diff --git a/packages/util/src/types.ts b/packages/util/src/types.ts index 6c007c0fe2..1c4c6e4a4d 100644 --- a/packages/util/src/types.ts +++ b/packages/util/src/types.ts @@ -1,24 +1,25 @@ -import { bufferToBigInt, bufferToHex, toBuffer } from './bytes' +import { bytesToHex } from 'ethereum-cryptography/utils' + +import { bytesToBigInt, toBytes } from './bytes' import { isHexString } from './internal' import type { Address } from './address' -import type { ToBufferInputTypes } from './bytes' +import type { ToBytesInputTypes } from './bytes' /* * A type that represents an input that can be converted to a BigInt. */ -export type BigIntLike = bigint | PrefixedHexString | number | Buffer +export type BigIntLike = bigint | PrefixedHexString | number | Uint8Array /* * A type that represents an input that can be converted to a Buffer. */ -export type BufferLike = - | Buffer +export type BytesLike = | Uint8Array | number[] | number | bigint - | TransformableToBuffer + | TransformabletoBytes | PrefixedHexString /* @@ -29,22 +30,10 @@ export type PrefixedHexString = string /** * A type that represents an input that can be converted to an Address. */ -export type AddressLike = Address | Buffer | PrefixedHexString +export type AddressLike = Address | Uint8Array | PrefixedHexString -/* - * A type that represents an object that has a `toArray()` method. - */ -export interface TransformableToArray { - toArray(): Uint8Array - toBuffer?(): Buffer -} - -/* - * A type that represents an object that has a `toBuffer()` method. - */ -export interface TransformableToBuffer { - toBuffer(): Buffer - toArray?(): Uint8Array +export interface TransformabletoBytes { + toBytes?(): Uint8Array } export type NestedUint8Array = Array @@ -56,14 +45,14 @@ export type NestedBufferArray = Array export enum TypeOutput { Number, BigInt, - Buffer, + Uint8Array, PrefixedHexString, } export type TypeOutputReturnType = { [TypeOutput.Number]: number [TypeOutput.BigInt]: bigint - [TypeOutput.Buffer]: Buffer + [TypeOutput.Uint8Array]: Uint8Array [TypeOutput.PrefixedHexString]: PrefixedHexString } @@ -76,11 +65,11 @@ export type TypeOutputReturnType = { export function toType(input: null, outputType: T): null export function toType(input: undefined, outputType: T): undefined export function toType( - input: ToBufferInputTypes, + input: ToBytesInputTypes, outputType: T ): TypeOutputReturnType[T] export function toType( - input: ToBufferInputTypes, + input: ToBytesInputTypes, outputType: T ): TypeOutputReturnType[T] | undefined | null { if (input === null) { @@ -98,15 +87,15 @@ export function toType( ) } - const output = toBuffer(input) + const output = toBytes(input) switch (outputType) { - case TypeOutput.Buffer: + case TypeOutput.Uint8Array: return output as TypeOutputReturnType[T] case TypeOutput.BigInt: - return bufferToBigInt(output) as TypeOutputReturnType[T] + return bytesToBigInt(output) as TypeOutputReturnType[T] case TypeOutput.Number: { - const bigInt = bufferToBigInt(output) + const bigInt = bytesToBigInt(output) if (bigInt > BigInt(Number.MAX_SAFE_INTEGER)) { throw new Error( 'The provided number is greater than MAX_SAFE_INTEGER (please use an alternative output type)' @@ -115,7 +104,7 @@ export function toType( return Number(bigInt) as TypeOutputReturnType[T] } case TypeOutput.PrefixedHexString: - return bufferToHex(output) as TypeOutputReturnType[T] + return bytesToHex(output) as TypeOutputReturnType[T] default: throw new Error('unknown outputType') } diff --git a/packages/util/src/withdrawal.ts b/packages/util/src/withdrawal.ts index 88a9ef5918..53042f9f00 100644 --- a/packages/util/src/withdrawal.ts +++ b/packages/util/src/withdrawal.ts @@ -1,5 +1,5 @@ import { Address } from './address' -import { bigIntToHex } from './bytes' +import { bigIntToHex, bytesToPrefixedHexString, toBytes } from './bytes' import { TypeOutput, toType } from './types' import type { AddressLike, BigIntLike } from './types' @@ -26,7 +26,7 @@ export interface JsonRpcWithdrawal { amount: string // QUANTITY - bigint amount in Gwei 8 bytes } -export type WithdrawalBuffer = [Buffer, Buffer, Buffer, Buffer] +export type WithdrawalBytes = [Uint8Array, Uint8Array, Uint8Array, Uint8Array] /** * Representation of EIP-4895 withdrawal data @@ -56,13 +56,13 @@ export class Withdrawal { } = withdrawalData const index = toType(indexData, TypeOutput.BigInt) const validatorIndex = toType(validatorIndexData, TypeOutput.BigInt) - const address = new Address(toType(addressData, TypeOutput.Buffer)) + const address = addressData instanceof Address ? addressData : new Address(toBytes(addressData)) const amount = toType(amountData, TypeOutput.BigInt) return new Withdrawal(index, validatorIndex, address, amount) } - public static fromValuesArray(withdrawalArray: WithdrawalBuffer) { + public static fromValuesArray(withdrawalArray: WithdrawalBytes) { if (withdrawalArray.length !== 4) { throw Error(`Invalid withdrawalArray length expected=4 actual=${withdrawalArray.length}`) } @@ -75,39 +75,36 @@ export class Withdrawal { * @param withdrawal the withdrawal to convert * @returns buffer array of the withdrawal */ - public static toBufferArray(withdrawal: Withdrawal | WithdrawalData): WithdrawalBuffer { + public static toBytesArray(withdrawal: Withdrawal | WithdrawalData): WithdrawalBytes { const { index, validatorIndex, address, amount } = withdrawal - const indexBuffer = + const indexBytes = toType(index, TypeOutput.BigInt) === BigInt(0) - ? Buffer.alloc(0) - : toType(index, TypeOutput.Buffer) - const validatorIndexBuffer = + ? new Uint8Array() + : toType(index, TypeOutput.Uint8Array) + const validatorIndexBytes = toType(validatorIndex, TypeOutput.BigInt) === BigInt(0) - ? Buffer.alloc(0) - : toType(validatorIndex, TypeOutput.Buffer) - let addressBuffer - if (address instanceof Address) { - addressBuffer = (
address).buf - } else { - addressBuffer = toType(address, TypeOutput.Buffer) - } - const amountBuffer = + ? new Uint8Array() + : toType(validatorIndex, TypeOutput.Uint8Array) + const addressBytes = + address instanceof Address ? (
address).bytes : toType(address, TypeOutput.Uint8Array) + + const amountBytes = toType(amount, TypeOutput.BigInt) === BigInt(0) - ? Buffer.alloc(0) - : toType(amount, TypeOutput.Buffer) + ? new Uint8Array() + : toType(amount, TypeOutput.Uint8Array) - return [indexBuffer, validatorIndexBuffer, addressBuffer, amountBuffer] + return [indexBytes, validatorIndexBytes, addressBytes, amountBytes] } raw() { - return Withdrawal.toBufferArray(this) + return Withdrawal.toBytesArray(this) } toValue() { return { index: this.index, validatorIndex: this.validatorIndex, - address: this.address.buf, + address: this.address.bytes, amount: this.amount, } } @@ -116,7 +113,7 @@ export class Withdrawal { return { index: bigIntToHex(this.index), validatorIndex: bigIntToHex(this.validatorIndex), - address: '0x' + this.address.buf.toString('hex'), + address: bytesToPrefixedHexString(this.address.bytes), amount: bigIntToHex(this.amount), } } diff --git a/packages/util/test/account.spec.ts b/packages/util/test/account.spec.ts index a2f3b7f342..082d3a477b 100644 --- a/packages/util/test/account.spec.ts +++ b/packages/util/test/account.spec.ts @@ -1,20 +1,26 @@ import { RLP } from '@ethereumjs/rlp' +import { bytesToHex, equalsBytes, hexToBytes, utf8ToBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' import { Account, - bufferToBigInt, + bytesToBigInt, + bytesToPrefixedHexString, generateAddress, generateAddress2, + hexStringToBytes, importPublic, + intToBytes, + intToHex, isValidAddress, isValidChecksumAddress, isValidPrivate, isValidPublic, + padToEven, privateToAddress, privateToPublic, publicToAddress, - toBuffer, + toBytes, toChecksumAddress, } from '../src' @@ -28,12 +34,12 @@ tape('Account', function (t) { st.equal(account.nonce, _0n, 'should have zero nonce') st.equal(account.balance, _0n, 'should have zero balance') st.equal( - account.storageRoot.toString('hex'), + bytesToHex(account.storageRoot), '56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421', 'should have storageRoot equal to KECCAK256_RLP' ) st.equal( - account.codeHash.toString('hex'), + bytesToHex(account.codeHash), 'c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470', 'should have codeHash equal to KECCAK256_NULL' ) @@ -47,16 +53,17 @@ tape('Account', function (t) { '0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421', // storageRoot '0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470', // codeHash ] - const account = Account.fromValuesArray(raw.map(toBuffer)) + const account = Account.fromValuesArray(raw.map((el) => hexStringToBytes(el))) + st.equal(account.nonce, BigInt(2), 'should have correct nonce') st.equal(account.balance, BigInt(900), 'should have correct balance') st.equal( - account.storageRoot.toString('hex'), + bytesToHex(account.storageRoot), '56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421', 'should have correct storageRoot' ) st.equal( - account.codeHash.toString('hex'), + bytesToHex(account.codeHash), 'c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470', 'should have correct codeHash' ) @@ -74,12 +81,12 @@ tape('Account', function (t) { st.equal(account.nonce, BigInt(2), 'should have correct nonce') st.equal(account.balance, BigInt(900), 'should have correct balance') st.equal( - account.storageRoot.toString('hex'), + bytesToHex(account.storageRoot), '56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421', 'should have correct storageRoot' ) st.equal( - account.codeHash.toString('hex'), + bytesToHex(account.codeHash), 'c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470', 'should have correct codeHash' ) @@ -87,20 +94,19 @@ tape('Account', function (t) { }) t.test('from RLP data', function (st) { - const accountRlp = Buffer.from( - 'f84602820384a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470', - 'hex' + const accountRlp = hexToBytes( + 'f84602820384a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470' ) const account = Account.fromRlpSerializedAccount(accountRlp) st.equal(account.nonce, BigInt(2), 'should have correct nonce') st.equal(account.balance, BigInt(900), 'should have correct balance') st.equal( - account.storageRoot.toString('hex'), + bytesToHex(account.storageRoot), '56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421', 'should have correct storageRoot' ) st.equal( - account.codeHash.toString('hex'), + bytesToHex(account.codeHash), 'c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470', 'should have correct codeHash' ) @@ -115,17 +121,15 @@ tape('Account', function (t) { codeHash: '0xc5d2461236f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470', } const account = Account.fromAccountData(raw) - const accountRlp = Buffer.from( - RLP.encode([raw.nonce, raw.balance, raw.storageRoot, raw.codeHash]) - ) - st.ok(account.serialize().equals(accountRlp), 'should serialize correctly') + const accountRlp = RLP.encode([raw.nonce, raw.balance, raw.storageRoot, raw.codeHash]) + + st.ok(equalsBytes(account.serialize(), accountRlp), 'should serialize correctly') st.end() }) t.test('isContract', function (st) { - const accountRlp = Buffer.from( - 'f84602820384a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470', - 'hex' + const accountRlp = hexToBytes( + 'f84602820384a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470' ) let account = Account.fromRlpSerializedAccount(accountRlp) st.notOk(account.isContract(), 'should return false for a non-contract account') @@ -158,11 +162,11 @@ tape('Account', function (t) { t.test('validation', function (st) { st.throws(() => { - new Account(undefined, undefined, Buffer.from('hey'), undefined) + new Account(undefined, undefined, hexToBytes('hey'), undefined) }, 'should only accept length 32 buffer for storageRoot') st.throws(() => { - new Account(undefined, undefined, undefined, Buffer.from('hey')) + new Account(undefined, undefined, undefined, hexToBytes('hey')) }, 'should only accept length 32 buffer for codeHash') const data = { balance: BigInt(5) } @@ -186,11 +190,11 @@ tape('Utility Functions', function (t) { const SECP256K1_N = BigInt('0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141') let tmp = '0011223344' - st.notOk(isValidPrivate(Buffer.from(tmp, 'hex')), 'should fail on short input') + st.notOk(isValidPrivate(hexToBytes(tmp)), 'should fail on short input') tmp = '3a443d8381a6798a70c6ff9304bdc8cb0163c23211d11628fae52ef9e0dca11a001cf066d56a8156fc201cd5df8a36ef694eecd258903fca7086c1fae7441e1d' - st.notOk(isValidPrivate(Buffer.from(tmp, 'hex')), 'should fail on too big input') + st.notOk(isValidPrivate(hexToBytes(tmp)), 'should fail on too big input') st.notOk( isValidPrivate(('WRONG_INPUT_TYPE') as Buffer), @@ -198,97 +202,82 @@ tape('Utility Functions', function (t) { ) tmp = '0000000000000000000000000000000000000000000000000000000000000000' - st.notOk(isValidPrivate(Buffer.from(tmp, 'hex')), 'should fail on invalid curve (zero)') + st.notOk(isValidPrivate(hexToBytes(tmp)), 'should fail on invalid curve (zero)') tmp = SECP256K1_N.toString(16) - st.notOk(isValidPrivate(Buffer.from(tmp, 'hex')), 'should fail on invalid curve (== N)') + st.notOk(isValidPrivate(hexToBytes(tmp)), 'should fail on invalid curve (== N)') tmp = (SECP256K1_N + BigInt(1)).toString(16) - st.notOk(isValidPrivate(Buffer.from(tmp, 'hex')), 'should fail on invalid curve (>= N)') + st.notOk(isValidPrivate(hexToBytes(tmp)), 'should fail on invalid curve (>= N)') tmp = (SECP256K1_N - BigInt(1)).toString(16) - st.ok(isValidPrivate(Buffer.from(tmp, 'hex')), 'should work otherwise (< N)') + st.ok(isValidPrivate(hexToBytes(tmp)), 'should work otherwise (< N)') st.end() }) t.test('isValidPublic', function (st) { - let pubKey = Buffer.from( - '3a443d8381a6798a70c6ff9304bdc8cb0163c23211d11628fae52ef9e0dca11a001cf066d56a8156fc201cd5df8a36ef694eecd258903fca7086c1fae744', - 'hex' + let pubKey = hexToBytes( + '3a443d8381a6798a70c6ff9304bdc8cb0163c23211d11628fae52ef9e0dca11a001cf066d56a8156fc201cd5df8a36ef694eecd258903fca7086c1fae744' ) st.notOk(isValidPublic(pubKey), 'should fail on too short input') - pubKey = Buffer.from( - '3a443d8381a6798a70c6ff9304bdc8cb0163c23211d11628fae52ef9e0dca11a001cf066d56a8156fc201cd5df8a36ef694eecd258903fca7086c1fae7441e1d00', - 'hex' + pubKey = hexToBytes( + '3a443d8381a6798a70c6ff9304bdc8cb0163c23211d11628fae52ef9e0dca11a001cf066d56a8156fc201cd5df8a36ef694eecd258903fca7086c1fae7441e1d00' ) st.notOk(isValidPublic(pubKey), 'should fail on too big input') - pubKey = Buffer.from( - '043a443d8381a6798a70c6ff9304bdc8cb0163c23211d11628fae52ef9e0dca11a001cf066d56a8156fc201cd5df8a36ef694eecd258903fca7086c1fae7441e1d', - 'hex' + pubKey = hexToBytes( + '043a443d8381a6798a70c6ff9304bdc8cb0163c23211d11628fae52ef9e0dca11a001cf066d56a8156fc201cd5df8a36ef694eecd258903fca7086c1fae7441e1d' ) st.notOk(isValidPublic(pubKey), 'should fail on SEC1 key') - pubKey = Buffer.from( - '043a443d8381a6798a70c6ff9304bdc8cb0163c23211d11628fae52ef9e0dca11a001cf066d56a8156fc201cd5df8a36ef694eecd258903fca7086c1fae7441e1d', - 'hex' + pubKey = hexToBytes( + '043a443d8381a6798a70c6ff9304bdc8cb0163c23211d11628fae52ef9e0dca11a001cf066d56a8156fc201cd5df8a36ef694eecd258903fca7086c1fae7441e1d' ) st.ok(isValidPublic(pubKey, true), "shouldn't fail on SEC1 key wt.testh sant.testize enabled") - pubKey = Buffer.from( - '023a443d8381a6798a70c6ff9304bdc8cb0163c23211d11628fae52ef9e0dca11a001cf066d56a8156fc201cd5df8a36ef694eecd258903fca7086c1fae7441e1d', - 'hex' + pubKey = hexToBytes( + '023a443d8381a6798a70c6ff9304bdc8cb0163c23211d11628fae52ef9e0dca11a001cf066d56a8156fc201cd5df8a36ef694eecd258903fca7086c1fae7441e1d' ) st.notOk(isValidPublic(pubKey), 'should fail wt.testh an invalid SEC1 public key') - pubKey = Buffer.from( - '03fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f', - 'hex' - ) + pubKey = hexToBytes('03fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f') st.notOk(isValidPublic(pubKey), 'should fail an invalid 33-byte public key') - pubKey = Buffer.from( - 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f0000000000000000000000000000000000000000000000000000000000000001', - 'hex' + pubKey = hexToBytes( + 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f0000000000000000000000000000000000000000000000000000000000000001' ) st.notOk(isValidPublic(pubKey), 'should fail an invalid 64-byte public key') - pubKey = Buffer.from( - '04fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f0000000000000000000000000000000000000000000000000000000000000001', - 'hex' + pubKey = hexToBytes( + '04fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f0000000000000000000000000000000000000000000000000000000000000001' ) st.notOk(isValidPublic(pubKey, true), 'should fail an invalid 65-byte public key') - pubKey = Buffer.from( - '033a443d8381a6798a70c6ff9304bdc8cb0163c23211d11628fae52ef9e0dca11a', - 'hex' - ) + pubKey = hexToBytes('033a443d8381a6798a70c6ff9304bdc8cb0163c23211d11628fae52ef9e0dca11a') st.ok( isValidPublic(pubKey, true), 'should work wt.testh compressed keys wt.testh sant.testize enabled' ) - pubKey = Buffer.from( - '043a443d8381a6798a70c6ff9304bdc8cb0163c23211d11628fae52ef9e0dca11a001cf066d56a8156fc201cd5df8a36ef694eecd258903fca7086c1fae7441e1d', - 'hex' + pubKey = hexToBytes( + '043a443d8381a6798a70c6ff9304bdc8cb0163c23211d11628fae52ef9e0dca11a001cf066d56a8156fc201cd5df8a36ef694eecd258903fca7086c1fae7441e1d' ) st.ok(isValidPublic(pubKey, true), 'should work wt.testh sant.testize enabled') - pubKey = Buffer.from( - '3a443d8381a6798a70c6ff9304bdc8cb0163c23211d11628fae52ef9e0dca11a001cf066d56a8156fc201cd5df8a36ef694eecd258903fca7086c1fae7441e1d', - 'hex' + pubKey = hexToBytes( + '3a443d8381a6798a70c6ff9304bdc8cb0163c23211d11628fae52ef9e0dca11a001cf066d56a8156fc201cd5df8a36ef694eecd258903fca7086c1fae7441e1d' ) st.ok(isValidPublic(pubKey), 'should work otherwise') pubKey = '3a443d8381a6798a70c6ff9304bdc8cb0163c23211d11628fae52ef9e0dca11a001cf066d56a8156fc201cd5df8a36ef694eecd258903fca7086c1fae7441e1d' as any try { - isValidPublic((pubKey) as Buffer) + isValidPublic((pubKey) as Uint8Array) } catch (err: any) { st.ok( - err.message.includes('This method only supports Buffer'), - 'should throw if input is not Buffer' + err.message.includes('This method only supports Uint8Array'), + 'should throw if input is not Uint8Array' ) } st.end() @@ -301,7 +290,7 @@ tape('Utility Functions', function (t) { let tmp = '3a443d8381a6798a70c6ff9304bdc8cb0163c23211d11628fae52ef9e0dca11a001cf066d56a8156fc201cd5df8a36ef694eecd258903fca7086c1fae7441e1d' st.equal( - importPublic(Buffer.from(tmp, 'hex')).toString('hex'), + bytesToHex(importPublic(hexToBytes(tmp))), pubKey, 'should work wt.testh an Ethereum public key' ) @@ -309,14 +298,14 @@ tape('Utility Functions', function (t) { tmp = '043a443d8381a6798a70c6ff9304bdc8cb0163c23211d11628fae52ef9e0dca11a001cf066d56a8156fc201cd5df8a36ef694eecd258903fca7086c1fae7441e1d' st.equal( - importPublic(Buffer.from(tmp, 'hex')).toString('hex'), + bytesToHex(importPublic(hexToBytes(tmp))), pubKey, 'should work wt.testh uncompressed SEC1 keys' ) tmp = '033a443d8381a6798a70c6ff9304bdc8cb0163c23211d11628fae52ef9e0dca11a' st.equal( - importPublic(Buffer.from(tmp, 'hex')).toString('hex'), + bytesToHex(importPublic(hexToBytes(tmp))), pubKey, 'should work wt.testh compressed SEC1 keys' ) @@ -328,33 +317,29 @@ tape('Utility Functions', function (t) { }) t.test('publicToAddress', function (st) { - let pubKey = Buffer.from( - '3a443d8381a6798a70c6ff9304bdc8cb0163c23211d11628fae52ef9e0dca11a001cf066d56a8156fc201cd5df8a36ef694eecd258903fca7086c1fae7441e1d', - 'hex' + let pubKey = hexToBytes( + '3a443d8381a6798a70c6ff9304bdc8cb0163c23211d11628fae52ef9e0dca11a001cf066d56a8156fc201cd5df8a36ef694eecd258903fca7086c1fae7441e1d' ) let address = '2f015c60e0be116b1f0cd534704db9c92118fb6a' let r = publicToAddress(pubKey) - st.equal(r.toString('hex'), address, 'should produce an address given a public key') + st.equal(bytesToHex(r), address, 'should produce an address given a public key') - pubKey = Buffer.from( - '043a443d8381a6798a70c6ff9304bdc8cb0163c23211d11628fae52ef9e0dca11a001cf066d56a8156fc201cd5df8a36ef694eecd258903fca7086c1fae7441e1d', - 'hex' + pubKey = hexToBytes( + '043a443d8381a6798a70c6ff9304bdc8cb0163c23211d11628fae52ef9e0dca11a001cf066d56a8156fc201cd5df8a36ef694eecd258903fca7086c1fae7441e1d' ) address = '2f015c60e0be116b1f0cd534704db9c92118fb6a' r = publicToAddress(pubKey, true) - st.equal(r.toString('hex'), address, 'should produce an address given a SEC1 public key') + st.equal(bytesToHex(r), address, 'should produce an address given a SEC1 public key') - pubKey = Buffer.from( - '023a443d8381a6798a70c6ff9304bdc8cb0163c23211d11628fae52ef9e0dca11a001cf066d56a8156fc201cd5df8a36ef694eecd258903fca7086c1fae7441e1d', - 'hex' + pubKey = hexToBytes( + '023a443d8381a6798a70c6ff9304bdc8cb0163c23211d11628fae52ef9e0dca11a001cf066d56a8156fc201cd5df8a36ef694eecd258903fca7086c1fae7441e1d' ) st.throws(function () { publicToAddress(pubKey, true) }, "shouldn't produce an address given an invalid SEC1 public key") - pubKey = Buffer.from( - '3a443d8381a6798a70c6ff9304bdc8cb0163c23211d11628fae52ef9e0dca11a001cf066d56a8156fc201cd5df8a36ef694eecd258903fca7086c1fae744', - 'hex' + pubKey = hexToBytes( + '3a443d8381a6798a70c6ff9304bdc8cb0163c23211d11628fae52ef9e0dca11a001cf066d56a8156fc201cd5df8a36ef694eecd258903fca7086c1fae744' ) st.throws(function () { publicToAddress(pubKey) @@ -364,45 +349,36 @@ tape('Utility Functions', function (t) { '0x3a443d8381a6798a70c6ff9304bdc8cb0163c23211d11628fae52ef9e0dca11a001cf066d56a8156fc201cd5df8a36ef694eecd258903fca7086c1fae7441e1d' as any st.throws(function () { publicToAddress(pubKey) - }, 'should throw if input is not a buffer') + }, 'should throw if input is not a Uint8Array') st.end() }) t.test('privateToPublic', function (st) { const pubKey = '3a443d8381a6798a70c6ff9304bdc8cb0163c23211d11628fae52ef9e0dca11a001cf066d56a8156fc201cd5df8a36ef694eecd258903fca7086c1fae7441e1d' - let privateKey = Buffer.from( - 'ea54bdc52d163f88c93ab0615782cf718a2efb9e51a7989aab1b08067e9c1c5f', - 'hex' - ) + let privateKey = hexToBytes('ea54bdc52d163f88c93ab0615782cf718a2efb9e51a7989aab1b08067e9c1c5f') const r = privateToPublic(privateKey) - st.equal(r.toString('hex'), pubKey, 'should produce a public key given a private key') + st.equal(bytesToHex(r), pubKey, 'should produce a public key given a private key') - privateKey = Buffer.from( - 'ea54bdc52d163f88c93ab0615782cf718a2efb9e51a7989aab1b08067e9c1c5f2a', - 'hex' - ) + privateKey = hexToBytes('ea54bdc52d163f88c93ab0615782cf718a2efb9e51a7989aab1b08067e9c1c5f2a') st.throws(function () { privateToPublic(privateKey) }, "shouldn't produce a public key given an invalid private key") - privateKey = Buffer.from( - 'ea54bdc52d163f88c93ab0615782cf718a2efb9e51a7989aab1b08067e9c1c', - 'hex' - ) + privateKey = hexToBytes('ea54bdc52d163f88c93ab0615782cf718a2efb9e51a7989aab1b08067e9c1c') st.throws(function () { privateToPublic(privateKey) }, "shouldn't produce a public key given an invalid private key") privateKey = '0xea54bdc52d163f88c93ab0615782cf718a2efb9e51a7989aab1b08067e9c1c5f' as any try { - privateToPublic((privateKey) as Buffer) + privateToPublic((privateKey) as Uint8Array) } catch (err: any) { st.ok( - err.message.includes('This method only supports Buffer'), - 'should throw if private key is not Buffer' + err.message.includes('This method only supports Uint8Array'), + 'should throw if private key is not Uint8Array' ) - st.ok(err.message.includes(privateKey), 'should throw if private key is not Buffer') + st.ok(err.message.includes(privateKey), 'should throw if private key is not Uint8Array') } st.end() }) @@ -410,35 +386,31 @@ tape('Utility Functions', function (t) { t.test('privateToAddress', function (st) { const address = '2f015c60e0be116b1f0cd534704db9c92118fb6a' // Our private key - const privateKey = Buffer.from( - 'ea54bdc52d163f88c93ab0615782cf718a2efb9e51a7989aab1b08067e9c1c5f', - 'hex' + const privateKey = hexToBytes( + 'ea54bdc52d163f88c93ab0615782cf718a2efb9e51a7989aab1b08067e9c1c5f' ) const r = privateToAddress(privateKey) - st.equal(r.toString('hex'), address, 'should produce an address given a private key') + st.equal(bytesToHex(r), address, 'should produce an address given a private key') st.end() }) t.test('generateAddress', function (st) { const addr = generateAddress( - Buffer.from('990ccf8a0de58091c028d6ff76bb235ee67c1c39', 'utf8'), - toBuffer(14) + utf8ToBytes('990ccf8a0de58091c028d6ff76bb235ee67c1c39'), + toBytes(14) ) st.equal( - addr.toString('hex'), + bytesToHex(addr), '936a4295d8d74e310c0c95f0a63e53737b998d12', 'should produce an address given a public key' ) st.end() }) - t.test('generateAddress wt.testh hex prefix', function (st) { - const addr = generateAddress( - toBuffer('0x990ccf8a0de58091c028d6ff76bb235ee67c1c39'), - toBuffer(14) - ) + t.test('generateAddress with hex prefix', function (st) { + const addr = generateAddress(toBytes('0x990ccf8a0de58091c028d6ff76bb235ee67c1c39'), toBytes(14)) st.equal( - addr.toString('hex'), + bytesToHex(addr), 'd658a4b8247c14868f3c512fa5cbb6e458e4a989', 'should produce an address given a public key' ) @@ -446,12 +418,9 @@ tape('Utility Functions', function (t) { }) t.test('generateAddress wt.testh nonce 0 (special case)', function (st) { - const addr = generateAddress( - toBuffer('0x990ccf8a0de58091c028d6ff76bb235ee67c1c39'), - toBuffer(0) - ) + const addr = generateAddress(toBytes('0x990ccf8a0de58091c028d6ff76bb235ee67c1c39'), toBytes(0)) st.equal( - addr.toString('hex'), + bytesToHex(addr), 'bfa69ba91385206bfdd2d8b9c1a5d6c10097a85b', 'should produce an address given a public key' ) @@ -460,17 +429,11 @@ tape('Utility Functions', function (t) { t.test('generateAddress wt.testh non-buffer inputs', function (st) { st.throws(function () { - generateAddress( - ('0x990ccf8a0de58091c028d6ff76bb235ee67c1c39') as Buffer, - toBuffer(0) - ) + generateAddress(('0x990ccf8a0de58091c028d6ff76bb235ee67c1c39') as Buffer, toBytes(0)) }, 'should throw if address is not Buffer') st.throws(function () { - generateAddress( - toBuffer('0x990ccf8a0de58091c028d6ff76bb235ee67c1c39'), - (0) as Buffer - ) + generateAddress(toBytes('0x990ccf8a0de58091c028d6ff76bb235ee67c1c39'), (0) as Buffer) }, 'should throw if nonce is not Buffer') st.end() }) @@ -478,9 +441,9 @@ tape('Utility Functions', function (t) { t.test('generateAddress2: EIP-1014 testdata examples', function (st) { for (const testdata of eip1014Testdata) { const { address, comment, result, salt, initCode } = testdata - const addr = generateAddress2(toBuffer(address), toBuffer(salt), toBuffer(initCode)) + const addr = generateAddress2(toBytes(address), toBytes(salt), toBytes(initCode)) st.equal( - '0x' + addr.toString('hex'), + '0x' + bytesToHex(addr), result, `${comment}: should generate the addresses provided` ) @@ -492,15 +455,15 @@ tape('Utility Functions', function (t) { const { address, salt, initCode } = eip1014Testdata[0] st.throws(function () { - generateAddress2((address) as Buffer, toBuffer(salt), toBuffer(initCode)) + generateAddress2((address) as Buffer, toBytes(salt), toBytes(initCode)) }, 'should throw if address is not Buffer') st.throws(function () { - generateAddress2(toBuffer(address), (salt) as Buffer, toBuffer(initCode)) + generateAddress2(toBytes(address), (salt) as Buffer, toBytes(initCode)) }, 'should throw if salt is not Buffer') st.throws(function () { - generateAddress2(toBuffer(address), toBuffer(salt), (initCode) as Buffer) + generateAddress2(toBytes(address), toBytes(salt), (initCode) as Buffer) }, 'should throw if initCode is not Buffer') st.end() }) @@ -562,7 +525,7 @@ tape('Utility Functions', function (t) { st.test('EIP55', function (st) { for (let i = 0; i < eip55ChecksumAddresses.length; i++) { const tmp = eip55ChecksumAddresses[i] - st.equal(toChecksumAddress(tmp.toLowerCase()), tmp) + st.equal(toChecksumAddress(tmp.toLowerCase()).toLowerCase(), tmp.toLowerCase()) } st.end() }) @@ -572,14 +535,17 @@ tape('Utility Functions', function (t) { for (const [chainId, addresses] of Object.entries(eip1191ChecksummAddresses)) { for (const addr of addresses) { st.equal(toChecksumAddress(addr.toLowerCase(), Number(chainId)), addr) - st.equal(toChecksumAddress(addr.toLowerCase(), Buffer.from([chainId] as any)), addr) - st.equal(toChecksumAddress(addr.toLowerCase(), BigInt(chainId)), addr) st.equal( - toChecksumAddress( - addr.toLowerCase(), - '0x' + Buffer.from([chainId] as any).toString('hex') - ), - addr + toChecksumAddress(addr.toLowerCase(), hexToBytes(padToEven(chainId))).toLowerCase(), + addr.toLowerCase() + ) + st.equal( + toChecksumAddress(addr.toLowerCase(), BigInt(chainId)).toLowerCase(), + addr.toLowerCase() + ) + st.equal( + toChecksumAddress(addr.toLowerCase(), '0x' + padToEven(chainId)).toLowerCase(), + addr.toLowerCase() ) } } @@ -587,14 +553,13 @@ tape('Utility Functions', function (t) { }) st.test('Should encode large chain ids greater than MAX_INTEGER correctly', function (st) { const addr = '0x88021160C5C792225E4E5452585947470010289D' - const chainIDBuffer = Buffer.from('796f6c6f763378', 'hex') - st.equal(toChecksumAddress(addr.toLowerCase(), chainIDBuffer), addr) - st.equal(toChecksumAddress(addr.toLowerCase(), bufferToBigInt(chainIDBuffer)), addr) - st.equal(toChecksumAddress(addr.toLowerCase(), '0x' + chainIDBuffer.toString('hex')), addr) - const chainIDNumber = parseInt(chainIDBuffer.toString('hex'), 16) - st.throws(() => { - toChecksumAddress(addr.toLowerCase(), chainIDNumber) - }) + const chainIDBytes = hexToBytes('796f6c6f763378') + st.equal(toChecksumAddress(addr.toLowerCase(), chainIDBytes), addr) + st.equal(toChecksumAddress(addr.toLowerCase(), bytesToBigInt(chainIDBytes)), addr) + st.equal( + toChecksumAddress(addr.toLowerCase(), bytesToPrefixedHexString(chainIDBytes)), + addr + ) st.end() }) st.end() @@ -626,11 +591,10 @@ tape('Utility Functions', function (t) { for (const [chainId, addresses] of Object.entries(eip1191ChecksummAddresses)) { for (const addr of addresses) { st.ok(isValidChecksumAddress(addr, Number(chainId))) - st.ok(isValidChecksumAddress(addr, Buffer.from([chainId] as any))) + st.ok(isValidChecksumAddress(addr, intToBytes(parseInt(chainId)))) st.ok(isValidChecksumAddress(addr, BigInt(chainId))) - st.equal( - isValidChecksumAddress(addr, '0x' + Buffer.from([chainId] as any).toString('hex')), - true + st.ok( + isValidChecksumAddress(addr, '0x' + padToEven(intToHex(parseInt(chainId)).slice(2))) ) } } diff --git a/packages/util/test/address.spec.ts b/packages/util/test/address.spec.ts index fcb5f97ebf..847e71decb 100644 --- a/packages/util/test/address.spec.ts +++ b/packages/util/test/address.spec.ts @@ -1,6 +1,7 @@ +import { equalsBytes, hexToBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' -import { Address, toBuffer } from '../src' +import { Address, hexStringToBytes, toBytes } from '../src' const eip1014Testdata = require('./testdata/eip1014Examples.json') @@ -12,14 +13,14 @@ tape('Address', (t) => { st.throws(() => Address.fromString(str)) const shortStr = '0x2f015c60e0be116b1f0cd534704db9c92118fb' st.throws(() => Address.fromString(shortStr)) - const buf = toBuffer(str) + const buf = toBytes(str) st.throws(() => new Address(buf)) st.end() }) t.test('should generate a zero address', (st) => { const addr = Address.zero() - st.deepEqual(addr.buf, toBuffer(ZERO_ADDR_S)) + st.deepEqual(addr.bytes, toBytes(ZERO_ADDR_S)) st.equal(addr.toString(), ZERO_ADDR_S) st.end() }) @@ -39,9 +40,8 @@ tape('Address', (t) => { }) t.test('should instantiate from public key', (st) => { - const pubKey = Buffer.from( - '3a443d8381a6798a70c6ff9304bdc8cb0163c23211d11628fae52ef9e0dca11a001cf066d56a8156fc201cd5df8a36ef694eecd258903fca7086c1fae7441e1d', - 'hex' + const pubKey = hexToBytes( + '3a443d8381a6798a70c6ff9304bdc8cb0163c23211d11628fae52ef9e0dca11a001cf066d56a8156fc201cd5df8a36ef694eecd258903fca7086c1fae7441e1d' ) const str = '0x2f015c60e0be116b1f0cd534704db9c92118fb6a' const addr = Address.fromPublicKey(pubKey) @@ -50,9 +50,8 @@ tape('Address', (t) => { }) t.test('should fail to instantiate from invalid public key', (st) => { - const pubKey = Buffer.from( - '3a443d8381a6798a70c6ff9304bdc8cb0163c23211d11628fae52ef9e0dca11a001cf066d56a8156fc201cd5df8a36ef694eecd258903fca7086c1fae744', - 'hex' + const pubKey = hexToBytes( + '3a443d8381a6798a70c6ff9304bdc8cb0163c23211d11628fae52ef9e0dca11a001cf066d56a8156fc201cd5df8a36ef694eecd258903fca7086c1fae744' ) st.throws(() => Address.fromPublicKey(pubKey)) st.end() @@ -60,7 +59,7 @@ tape('Address', (t) => { t.test('should instantiate from private key', (st) => { // prettier-ignore - const privateKey = Buffer.from([234, 84, 189, 197, 45, 22, 63, 136, 201, 58, 176, 97, 87, 130, 207, 113, 138, 46, 251, 158, 81, 167, 152, 154, 171, 27, 8, 6, 126, 156, 28, 95]) + const privateKey = Uint8Array.from([234, 84, 189, 197, 45, 22, 63, 136, 201, 58, 176, 97, 87, 130, 207, 113, 138, 46, 251, 158, 81, 167, 152, 154, 171, 27, 8, 6, 126, 156, 28, 95]) const str = '0x2f015c60e0be116b1f0cd534704db9c92118fb6a' const addr = Address.fromPrivateKey(privateKey) st.equal(addr.toString(), str) @@ -89,17 +88,17 @@ tape('Address', (t) => { for (const testdata of eip1014Testdata) { const { address, salt, initCode, result } = testdata const from = Address.fromString(address) - const addr = Address.generate2(from, toBuffer(salt), toBuffer(initCode)) + const addr = Address.generate2(from, toBytes(salt), toBytes(initCode)) st.equal(addr.toString(), result) } st.end() }) - t.test('should provide a buffer that does not mutate the original address', (st) => { + t.test('should provide a Uint8Array that does not mutate the original address', (st) => { const str = '0x2f015c60e0be116b1f0cd534704db9c92118fb6a' const address = Address.fromString(str) - const addressBuf = address.toBuffer() - addressBuf.fill(0) + const addressBytes = address.toBytes() + addressBytes.fill(0) st.equal(address.toString(), str) st.end() }) @@ -107,9 +106,9 @@ tape('Address', (t) => { t.test('should compare equality properly', (st) => { const str = '0x2f015c60e0be116b1f0cd534704db9c92118fb6a' const address1 = Address.fromString(str) - const address2 = new Address(Buffer.from(str.slice(2), 'hex')) + const address2 = new Address(hexStringToBytes(str)) st.ok(address1.equals(address2)) - st.ok(address1.buf.equals(address2.buf)) + st.ok(equalsBytes(address1.bytes, address2.bytes)) const str2 = '0xcd4EC7b66fbc029C116BA9Ffb3e59351c20B5B06' const address3 = Address.fromString(str2) diff --git a/packages/util/test/bytes.spec.ts b/packages/util/test/bytes.spec.ts index 40f27377fc..497ff4a2e0 100644 --- a/packages/util/test/bytes.spec.ts +++ b/packages/util/test/bytes.spec.ts @@ -1,30 +1,28 @@ +import { bytesToHex, equalsBytes, hexToBytes, utf8ToBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' import { Address, addHexPrefix, - arrToBufArr, - baToJSON, - bigIntToBuffer, + bigIntToBytes, bigIntToHex, - bigIntToUnpaddedBuffer, - bufArrToArr, - bufferToBigInt, - bufferToHex, - bufferToInt, + bigIntToUnpaddedBytes, + bytesToBigInt, + bytesToInt, + bytesToPrefixedHexString, fromSigned, - intToBuffer, + intToBytes, intToHex, - intToUnpaddedBuffer, + intToUnpaddedBytes, isZeroAddress, setLengthLeft, setLengthRight, short, - toBuffer, + toBytes, toUnsigned, toUtf8, unpadArray, - unpadBuffer, + unpadBytes, unpadHexString, validateNoLeadingZeroes, zeroAddress, @@ -35,7 +33,7 @@ tape('zeros function', function (t) { t.test('should produce lots of 0s', function (st) { const z60 = zeros(30) const zs60 = '000000000000000000000000000000000000000000000000000000000000' - st.equal(z60.toString('hex'), zs60) + st.equal(bytesToHex(z60), zs60) st.end() }) }) @@ -65,16 +63,16 @@ tape('is zero address', function (t) { }) }) -tape('unpadBuffer', function (t) { - t.test('should unpad a Buffer', function (st) { - const buf = toBuffer('0x0000000006600') - const r = unpadBuffer(buf) - st.ok(r.equals(toBuffer('0x6600'))) +tape('unpadBytes', function (t) { + t.test('should unpad a Uint8Array', function (st) { + const bytes = toBytes('0x0000000006600') + const r = unpadBytes(bytes) + st.deepEquals(r, toBytes('0x6600')) st.end() }) - t.test('should throw if input is not a Buffer', function (st) { + t.test('should throw if input is not a Uint8Array', function (st) { st.throws(function () { - unpadBuffer(('0000000006600') as Buffer) + unpadBytes(('0000000006600') as Uint8Array) }) st.end() }) @@ -89,7 +87,7 @@ tape('unpadArray', function (t) { }) t.test('should throw if input is not an Array', function (st) { st.throws(function () { - unpadArray((toBuffer([0, 0, 0, 1])) as number[]) + unpadArray((toBytes([0, 0, 0, 1])) as number[]) }) st.end() }) @@ -111,19 +109,19 @@ tape('unpadHexString', function (t) { }) tape('setLengthLeft', function (t) { - t.test('should left pad a Buffer', function (st) { - const buf = Buffer.from([9, 9]) - const padded = setLengthLeft(buf, 3) - st.equal(padded.toString('hex'), '000909') + t.test('should left pad a Uint8Array', function (st) { + const bytes = new Uint8Array([9, 9]) + const padded = setLengthLeft(bytes, 3) + st.equal(bytesToHex(padded), '000909') st.end() }) - t.test('should left truncate a Buffer', function (st) { - const buf = Buffer.from([9, 0, 9]) - const padded = setLengthLeft(buf, 2) - st.equal(padded.toString('hex'), '0009') + t.test('should left truncate a Uint8Array', function (st) { + const bytes = new Uint8Array([9, 0, 9]) + const padded = setLengthLeft(bytes, 2) + st.equal(bytesToHex(padded), '0009') st.end() }) - t.test('should throw if input is not a Buffer', function (st) { + t.test('should throw if input is not a Uint8Array', function (st) { st.throws(function () { setLengthLeft(([9, 9]) as Buffer, 3) }) @@ -132,70 +130,70 @@ tape('setLengthLeft', function (t) { }) tape('setLengthRight', function (t) { - t.test('should right pad a Buffer', function (st) { - const buf = Buffer.from([9, 9]) - const padded = setLengthRight(buf, 3) - st.equal(padded.toString('hex'), '090900') + t.test('should right pad a Uint8Array', function (st) { + const bytes = new Uint8Array([9, 9]) + const padded = setLengthRight(bytes, 3) + st.equal(bytesToHex(padded), '090900') st.end() }) - t.test('should right truncate a Buffer', function (st) { - const buf = Buffer.from([9, 0, 9]) - const padded = setLengthRight(buf, 2) - st.equal(padded.toString('hex'), '0900') + t.test('should right truncate a Uint8Array', function (st) { + const bytes = new Uint8Array([9, 0, 9]) + const padded = setLengthRight(bytes, 2) + st.equal(bytesToHex(padded), '0900') st.end() }) - t.test('should throw if input is not a Buffer', function (st) { + t.test('should throw if input is not a Uint8Array', function (st) { st.throws(function () { - setLengthRight(([9, 9]) as Buffer, 3) + setLengthRight(([9, 9]) as Uint8Array, 3) }) st.end() }) }) -tape('bufferToHex', function (t) { - t.test('should convert a buffer to hex', function (st) { - const buf = Buffer.from('5b9ac8', 'hex') - const hex = bufferToHex(buf) +tape('bytesToPrefixedHexString', function (t) { + t.test('should convert a Uint8Array to a prefixed hex string', function (st) { + const bytes = hexToBytes('5b9ac8') + const hex = bytesToPrefixedHexString(bytes) st.equal(hex, '0x5b9ac8') st.end() }) - t.test('empty buffer', function (st) { - const buf = Buffer.alloc(0) - const hex = bufferToHex(buf) + t.test('empty Uint8Array', function (st) { + const bytes = new Uint8Array() + const hex = bytesToPrefixedHexString(bytes) st.strictEqual(hex, '0x') st.end() }) }) -tape('bufferToInt', function (t) { +tape('bytesToInt', function (t) { t.test('should convert an int to hex', function (st) { - const buf = Buffer.from('5b9ac8', 'hex') - const i = bufferToInt(buf) + const bytes = hexToBytes('5b9ac8') + const i = bytesToInt(bytes) st.equal(i, 6003400) - st.equal(bufferToInt(Buffer.allocUnsafe(0)), 0) + st.equal(bytesToInt(new Uint8Array()), 0) st.end() }) t.test('should convert empty input to 0', function (st) { - st.equal(bufferToInt(Buffer.allocUnsafe(0)), 0) + st.equal(bytesToInt(new Uint8Array()), 0) st.end() }) }) tape('fromSigned', function (t) { - t.test('should convert an unsigned (negative) buffer to a signed number', function (st) { + t.test('should convert an unsigned (negative) Uint8Array to a signed number', function (st) { const neg = '-452312848583266388373324160190187140051835877600158453279131187530910662656' - const buf = Buffer.allocUnsafe(32).fill(0) - buf[0] = 255 + const bytes = zeros(32) + bytes[0] = 255 - st.equal(fromSigned(buf).toString(), neg) + st.equal(fromSigned(bytes).toString(), neg) st.end() }) - t.test('should convert an unsigned (positive) buffer to a signed number', function (st) { + t.test('should convert an unsigned (positive) Uint8Array to a signed number', function (st) { const neg = '452312848583266388373324160190187140051835877600158453279131187530910662656' - const buf = Buffer.allocUnsafe(32).fill(0) - buf[0] = 1 + const bytes = zeros(32) + bytes[0] = 1 - st.equal(fromSigned(buf).toString(), neg) + st.equal(fromSigned(bytes).toString(), neg) st.end() }) }) @@ -206,7 +204,7 @@ tape('toUnsigned', function (t) { const hex = 'ff00000000000000000000000000000000000000000000000000000000000000' const num = BigInt(neg) - st.equal(toUnsigned(num).toString('hex'), hex) + st.equal(bytesToHex(toUnsigned(num)), hex) st.end() }) @@ -215,7 +213,7 @@ tape('toUnsigned', function (t) { const hex = '0100000000000000000000000000000000000000000000000000000000000000' const num = BigInt(neg) - st.equal(toUnsigned(num).toString('hex'), hex) + st.equal(bytesToHex(toUnsigned(num)), hex) st.end() }) }) @@ -241,22 +239,22 @@ tape('short', function (t) { st.end() }) t.test('should short buffer', function (st) { - st.equal(short(Buffer.from(string, 'hex')), shortened) + st.equal(short(hexToBytes(string)), shortened) st.end() }) t.test('should short buffer to 10 chars', function (st) { - st.equal(short(Buffer.from(string, 'hex'), 10), shortenedToTen) + st.equal(short(hexToBytes(string), 10), shortenedToTen) st.end() }) }) tape('toUtf8', function (t) { t.test('toUtf8', (st) => { - let input = Buffer.from('hello').toString('hex') // '68656c6c6f' + let input = bytesToHex(utf8ToBytes('hello')) // '68656c6c6f' st.equal(toUtf8(input), 'hello', 'should convert a non-hex-prefixed value') st.equal(toUtf8(`0x${input}`), 'hello', 'should convert a hex-prefixed value') - input = Buffer.from('bip').toString('hex') // '626970' + input = bytesToHex(utf8ToBytes('bip')) // '626970' st.equal(toUtf8(input), 'bip', 'should handle trailing single 0s correctly') input = '657468657265756d000000000000000000000000000000000000000000000000' @@ -273,92 +271,81 @@ tape('toUtf8', function (t) { }) }) -tape('toBuffer', function (t) { +tape('toBytes', function (t) { t.test('should work', function (st) { // Buffer - st.ok(toBuffer(Buffer.allocUnsafe(0)).equals(Buffer.allocUnsafe(0))) + st.ok(equalsBytes(toBytes(new Uint8Array(0)), new Uint8Array())) // Array - st.ok(toBuffer([]).equals(Buffer.allocUnsafe(0))) + st.ok(equalsBytes(toBytes([]), new Uint8Array())) // String - st.ok(toBuffer('0x11').equals(Buffer.from([17]))) - st.equal(toBuffer('0x1234').toString('hex'), '1234') - st.ok(toBuffer('0x').equals(Buffer.from([]))) + st.ok(equalsBytes(toBytes('0x11'), Uint8Array.from([17]))) + st.equal(bytesToHex(toBytes('0x1234')), '1234') + st.ok(equalsBytes(toBytes('0x'), Uint8Array.from([]))) // Number - st.ok(toBuffer(1).equals(Buffer.from([1]))) + st.ok(equalsBytes(toBytes(1), Uint8Array.from([1]))) // null - st.ok(toBuffer(null).equals(Buffer.allocUnsafe(0))) + st.ok(equalsBytes(toBytes(null), new Uint8Array(0))) // undefined - st.ok(toBuffer(undefined).equals(Buffer.allocUnsafe(0))) + st.deepEquals(toBytes(undefined), new Uint8Array(0)) // BigInt - st.ok(toBuffer(BigInt(1)).equals(Buffer.from([1]))) + st.deepEquals(toBytes(BigInt(1)), Uint8Array.from([1])) // 'toArray' - st.ok( - toBuffer({ - toArray(): any { - return [1] + st.deepEquals( + toBytes({ + toBytes(): any { + return Uint8Array.from([1]) }, - }).equals(Buffer.from([1])) + }), + Uint8Array.from([1]) ) st.end() }) t.test('should fail', function (st) { st.throws(function () { - toBuffer({ test: 1 } as any) + toBytes({ test: 1 } as any) }) st.throws(function () { - toBuffer(BigInt(-10)) + toBytes(BigInt(-10)) }) st.end() }) t.test('should fail with non 0x-prefixed hex strings', function (st) { - st.throws(() => toBuffer('11'), '11') - st.throws(() => toBuffer('')) - st.throws(() => toBuffer('0xR'), '0xR') + st.throws(() => toBytes('11'), '11') + st.throws(() => toBytes('')) + st.throws(() => toBytes('0xR'), '0xR') st.end() }) t.test( - 'should convert a TransformableToBuffer like the Address class (i.e. provides a toBuffer method)', + 'should convert a TransformabletoBytes like the Address class (i.e. provides a toBytes method)', function (st) { const str = '0x2f015c60e0be116b1f0cd534704db9c92118fb6a' const address = Address.fromString(str) - const addressBuf = toBuffer(address) - st.ok(addressBuf.equals(address.toBuffer())) + const addressBytes = toBytes(address) + st.deepEquals(addressBytes, address.toBytes()) st.end() } ) }) -tape('baToJSON', function (t) { - t.test('should turn a array of buffers into a pure json object', function (st) { - const ba = [Buffer.from([0]), Buffer.from([1]), [Buffer.from([2])]] - st.deepEqual(baToJSON(ba), ['0x00', '0x01', ['0x02']]) - st.end() - }) - t.test('should turn a buffers into string', function (st) { - st.deepEqual(baToJSON(Buffer.from([0])), '0x00') - st.end() - }) -}) - -tape('intToBuffer', function (st) { - st.throws(() => intToBuffer('test'), 'throws on string') - st.throws(() => intToBuffer(Infinity), 'throws on +Infinity') - st.throws(() => intToBuffer(-Infinity), 'throws on -Infinity') - st.throws(() => intToBuffer(NaN), 'throws on NaN') - st.throws(() => intToBuffer(undefined), 'throws on undefined') - st.throws(() => intToBuffer(null), 'throws on null') - st.throws(() => intToBuffer(-1), 'throws on negative numbers') - st.throws(() => intToBuffer(1.05), 'throws on decimal numbers') - st.throws(() => intToBuffer({}), 'throws on objects') - st.throws(() => intToBuffer(true), 'throws on true') - st.throws(() => intToBuffer(false), 'throws on false') - st.throws(() => intToBuffer([]), 'throws on arrays') - st.throws(() => intToBuffer((() => {})), 'throws on arrays') - st.throws(() => intToBuffer(Number.MAX_SAFE_INTEGER + 1), 'throws on unsafe integers') - st.ok(intToBuffer(0).equals(Buffer.from('00', 'hex')), 'correctly converts 0 to a buffer') - st.ok(intToBuffer(1).equals(Buffer.from('01', 'hex')), 'correctly converts 1 to a buffer') +tape('intToBytes', function (st) { + st.throws(() => intToBytes('test'), 'throws on string') + st.throws(() => intToBytes(Infinity), 'throws on +Infinity') + st.throws(() => intToBytes(-Infinity), 'throws on -Infinity') + st.throws(() => intToBytes(NaN), 'throws on NaN') + st.throws(() => intToBytes(undefined), 'throws on undefined') + st.throws(() => intToBytes(null), 'throws on null') + st.throws(() => intToBytes(-1), 'throws on negative numbers') + st.throws(() => intToBytes(1.05), 'throws on decimal numbers') + st.throws(() => intToBytes({}), 'throws on objects') + st.throws(() => intToBytes(true), 'throws on true') + st.throws(() => intToBytes(false), 'throws on false') + st.throws(() => intToBytes([]), 'throws on arrays') + st.throws(() => intToBytes((() => {})), 'throws on arrays') + st.throws(() => intToBytes(Number.MAX_SAFE_INTEGER + 1), 'throws on unsafe integers') + st.deepEquals(intToBytes(0), hexToBytes('00'), 'correctly converts 0 to a Uint8Array') + st.deepEquals(intToBytes(1), hexToBytes('01'), 'correctly converts 1 to a Uint8Array') st.end() }) @@ -384,19 +371,19 @@ tape('intToHex', function (st) { tape('validateNoLeadingZeroes', function (st) { const noLeadingZeroes = { - a: toBuffer('0x123'), + a: toBytes('0x123'), } const noleadingZeroBytes = { - a: toBuffer('0x01'), + a: toBytes('0x01'), } const leadingZeroBytes = { - a: toBuffer('0x001'), + a: toBytes('0x001'), } const onlyZeroes = { - a: toBuffer('0x0'), + a: toBytes('0x0'), } const emptyBuffer = { - a: toBuffer('0x'), + a: toBytes('0x'), } const undefinedValue = { @@ -424,74 +411,30 @@ tape('validateNoLeadingZeroes', function (st) { st.end() }) -tape('arrToBufArr', function (st) { - const uint8 = Uint8Array.from([0, 1, 2]) - const uint8Arr = [ - Uint8Array.from([1, 2, 3]), - Uint8Array.from([4, 5, 6]), - [Uint8Array.from([7, 8, 9]), Uint8Array.from([1, 0, 0]), [Uint8Array.from([1, 1, 1])]], - ] - const buf = Buffer.from(uint8) - const bufArr = [ - Buffer.from(Uint8Array.from([1, 2, 3])), - Buffer.from(Uint8Array.from([4, 5, 6])), - [ - Buffer.from(Uint8Array.from([7, 8, 9])), - Buffer.from(Uint8Array.from([1, 0, 0])), - [Buffer.from(Uint8Array.from([1, 1, 1]))], - ], - ] - st.deepEqual(arrToBufArr(uint8), buf) - st.deepEqual(arrToBufArr(uint8Arr), bufArr) - st.end() -}) - -tape('bufArrToArr', function (st) { - const buf = Buffer.from('123', 'hex') - const bufArr = [ - Buffer.from('123', 'hex'), - Buffer.from('456', 'hex'), - [Buffer.from('789', 'hex'), Buffer.from('100', 'hex'), [Buffer.from('111', 'hex')]], - ] - const uint8 = Uint8Array.from(buf) - const uint8Arr = [ - Uint8Array.from(Buffer.from('123', 'hex')), - Uint8Array.from(Buffer.from('456', 'hex')), - [ - Uint8Array.from(Buffer.from('789', 'hex')), - Uint8Array.from(Buffer.from('100', 'hex')), - [Uint8Array.from(Buffer.from('111', 'hex'))], - ], - ] - st.deepEqual(bufArrToArr(buf), uint8) - st.deepEqual(bufArrToArr(bufArr), uint8Arr) - st.end() -}) - -tape('bufferToBigInt', (st) => { - const buf = toBuffer('0x123') - st.equal(BigInt(0x123), bufferToBigInt(buf)) +tape('bytesToBigInt', (st) => { + const buf = toBytes('0x123') + st.equal(BigInt(0x123), bytesToBigInt(buf)) st.end() }) -tape('bigIntToBuffer', (st) => { +tape('bigIntToBytes', (st) => { const num = BigInt(0x123) - st.deepEqual(toBuffer('0x123'), bigIntToBuffer(num)) + st.deepEqual(toBytes('0x123'), bigIntToBytes(num)) st.end() }) -tape('bigIntToUnpaddedBuffer', function (t) { +tape('bigIntToUnpaddedBytes', function (t) { t.test('should equal unpadded buffer value', function (st) { - st.ok(bigIntToUnpaddedBuffer(BigInt(0)).equals(Buffer.from([]))) - st.ok(bigIntToUnpaddedBuffer(BigInt(100)).equals(Buffer.from('64', 'hex'))) + st.deepEquals(bigIntToUnpaddedBytes(BigInt(0)), Uint8Array.from([])) + st.deepEquals(bigIntToUnpaddedBytes(BigInt(100)), hexToBytes('64')) st.end() }) }) -tape('intToUnpaddedBuffer', function (t) { +tape('intToUnpaddedBytes', function (t) { t.test('should equal unpadded buffer value', function (st) { - st.ok(intToUnpaddedBuffer(0).equals(Buffer.from([]))) - st.ok(intToUnpaddedBuffer(100).equals(Buffer.from('64', 'hex'))) + st.deepEquals(intToUnpaddedBytes(0), Uint8Array.from([])) + st.deepEquals(intToUnpaddedBytes(100), hexToBytes('64')) st.end() }) }) diff --git a/packages/util/test/constants.spec.ts b/packages/util/test/constants.spec.ts index ecec5b7978..18f0de0065 100644 --- a/packages/util/test/constants.spec.ts +++ b/packages/util/test/constants.spec.ts @@ -1,3 +1,4 @@ +import { bytesToHex } from 'ethereum-cryptography/utils' import * as tape from 'tape' import { @@ -31,7 +32,7 @@ tape('constants', function (t) { st.equal(KECCAK256_NULL_S, 'c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470') st.equal( - KECCAK256_NULL.toString('hex'), + bytesToHex(KECCAK256_NULL), 'c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470' ) @@ -41,14 +42,14 @@ tape('constants', function (t) { ) st.equal( - KECCAK256_RLP_ARRAY.toString('hex'), + bytesToHex(KECCAK256_RLP_ARRAY), '1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347' ) st.equal(KECCAK256_RLP_S, '56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421') st.equal( - KECCAK256_RLP.toString('hex'), + bytesToHex(KECCAK256_RLP), '56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421' ) diff --git a/packages/util/test/encoding.spec.ts b/packages/util/test/encoding.spec.ts index c28bc7e63a..9bc46c1f95 100644 --- a/packages/util/test/encoding.spec.ts +++ b/packages/util/test/encoding.spec.ts @@ -1,3 +1,4 @@ +import { hexToBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' import { bytesToNibbles, compactBytesToNibbles, nibblesToCompactBytes } from '../src' @@ -7,23 +8,23 @@ tape('encoding', function (t) { 'nibblesToCompactBytes and compactBytesToNibbles should encode hex data correctly', function (t) { const tests = [ - { hex: new Uint8Array(), compact: new Uint8Array(Buffer.from('00', 'hex')) }, - { hex: new Uint8Array([16]), compact: new Uint8Array(Buffer.from('20', 'hex')) }, + { hex: new Uint8Array(), compact: hexToBytes('00') }, + { hex: new Uint8Array([16]), compact: hexToBytes('20') }, { hex: new Uint8Array([1, 2, 3, 4, 5]), - compact: new Uint8Array(Buffer.from('112345', 'hex')), + compact: hexToBytes('112345'), }, { hex: new Uint8Array([0, 1, 2, 3, 4, 5]), - compact: new Uint8Array(Buffer.from('00012345', 'hex')), + compact: hexToBytes('00012345'), }, { hex: new Uint8Array([15, 1, 12, 11, 8, 16]), - compact: new Uint8Array(Buffer.from('3f1cb8', 'hex')), + compact: hexToBytes('3f1cb8'), }, { hex: new Uint8Array([0, 15, 1, 12, 11, 8, 16]), - compact: new Uint8Array(Buffer.from('200f1cb8', 'hex')), + compact: hexToBytes('200f1cb8'), }, ] @@ -42,15 +43,15 @@ tape('encoding', function (t) { { key: new Uint8Array(), hexOut: new Uint8Array([16]) }, { key: new Uint8Array(), hexOut: new Uint8Array([16]) }, { - key: new Uint8Array(Buffer.from('123456', 'hex')), + key: hexToBytes('123456'), hexOut: new Uint8Array([1, 2, 3, 4, 5, 6, 16]), }, { - key: new Uint8Array(Buffer.from('123405', 'hex')), + key: hexToBytes('123405'), hexOut: new Uint8Array([1, 2, 3, 4, 0, 5, 16]), }, { - key: new Uint8Array(Buffer.from('123456', 'hex')), + key: hexToBytes('123456'), hexOut: new Uint8Array([1, 2, 3, 4, 5, 6, 16]), }, ] diff --git a/packages/util/test/internal.spec.ts b/packages/util/test/internal.spec.ts index 4ebef620ed..d81624654f 100644 --- a/packages/util/test/internal.spec.ts +++ b/packages/util/test/internal.spec.ts @@ -1,3 +1,4 @@ +import { bytesToUtf8, utf8ToBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' import { @@ -11,7 +12,7 @@ import { toAscii, } from '../src/internal' -const buf = Buffer.from('hello') +const buf = utf8ToBytes('hello') tape('internal', (t) => { t.test('isHexPrefixed', (st) => { @@ -41,7 +42,7 @@ tape('internal', (t) => { st.end() }) t.test('toAscii', (st) => { - st.equal(toAscii(buf.toString('ascii')), '\x00\x00\x00') + st.equal(toAscii(bytesToUtf8(buf)), '\x00\x00\x00') st.end() }) t.test('getKeys', (st) => { diff --git a/packages/util/test/signature.spec.ts b/packages/util/test/signature.spec.ts index a466c612e9..0d7571fdf5 100644 --- a/packages/util/test/signature.spec.ts +++ b/packages/util/test/signature.spec.ts @@ -1,8 +1,9 @@ +import { hexToBytes, utf8ToBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' import { - bigIntToBuffer, - bufferToBigInt, + bigIntToBytes, + bytesToBigInt, ecrecover, ecsign, fromRpcSig, @@ -13,28 +14,20 @@ import { toRpcSig, } from '../src' -const echash = Buffer.from( - '82ff40c0a986c6a5cfad4ddf4c3aa6996f1a7837f9c398e17e5de5cbd5a12b28', - 'hex' -) -const ecprivkey = Buffer.from( - '3c9229289a6125f7fdf1885a77bb12c37a8d3b4962d936f7e3084dece32a3ca1', - 'hex' -) +const echash = hexToBytes('82ff40c0a986c6a5cfad4ddf4c3aa6996f1a7837f9c398e17e5de5cbd5a12b28') +const ecprivkey = hexToBytes('3c9229289a6125f7fdf1885a77bb12c37a8d3b4962d936f7e3084dece32a3ca1') const chainId = BigInt(3) // ropsten tape('ecsign', function (t) { t.test('should produce a signature', function (st) { const sig = ecsign(echash, ecprivkey) - st.ok( - sig.r.equals( - Buffer.from('99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1abe9', 'hex') - ) + st.deepEquals( + sig.r, + hexToBytes('99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1abe9') ) - st.ok( - sig.s.equals( - Buffer.from('129ff05af364204442bdb53ab6f18a99ab48acc9326fa689f228040429e3ca66', 'hex') - ) + st.deepEquals( + sig.s, + hexToBytes('129ff05af364204442bdb53ab6f18a99ab48acc9326fa689f228040429e3ca66') ) st.equal(sig.v, BigInt(27)) st.end() @@ -42,33 +35,29 @@ tape('ecsign', function (t) { t.test('should produce a signature for Ropsten testnet', function (st) { const sig = ecsign(echash, ecprivkey, chainId) - st.ok( - sig.r.equals( - Buffer.from('99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1abe9', 'hex') - ) + st.deepEquals( + sig.r, + hexToBytes('99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1abe9') ) - st.ok( - sig.s.equals( - Buffer.from('129ff05af364204442bdb53ab6f18a99ab48acc9326fa689f228040429e3ca66', 'hex') - ) + st.deepEquals( + sig.s, + hexToBytes('129ff05af364204442bdb53ab6f18a99ab48acc9326fa689f228040429e3ca66') ) st.equal(sig.v, BigInt(41)) st.end() }) t.test('should produce a signature for chainId=150', function (st) { - const expectedSigR = Buffer.from( - '99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1abe9', - 'hex' + const expectedSigR = hexToBytes( + '99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1abe9' ) - const expectedSigS = Buffer.from( - '129ff05af364204442bdb53ab6f18a99ab48acc9326fa689f228040429e3ca66', - 'hex' + const expectedSigS = hexToBytes( + '129ff05af364204442bdb53ab6f18a99ab48acc9326fa689f228040429e3ca66' ) const sig = ecsign(echash, ecprivkey, BigInt(150)) - st.ok(sig.r.equals(expectedSigR)) - st.ok(sig.s.equals(expectedSigS)) + st.deepEquals(sig.r, expectedSigR) + st.deepEquals(sig.s, expectedSigS) st.equal(sig.v, BigInt(150 * 2 + 35)) st.end() @@ -77,20 +66,18 @@ tape('ecsign', function (t) { t.test( 'should produce a signature for a high number chainId greater than MAX_SAFE_INTEGER', function (st) { - const chainIDBuffer = Buffer.from('796f6c6f763378', 'hex') - const expectedSigR = Buffer.from( - '99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1abe9', - 'hex' + const chainIDBuffer = hexToBytes('796f6c6f763378') + const expectedSigR = hexToBytes( + '99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1abe9' ) - const expectedSigS = Buffer.from( - '129ff05af364204442bdb53ab6f18a99ab48acc9326fa689f228040429e3ca66', - 'hex' + const expectedSigS = hexToBytes( + '129ff05af364204442bdb53ab6f18a99ab48acc9326fa689f228040429e3ca66' ) const expectedSigV = BigInt('68361967398315795') - const sigBuffer = ecsign(echash, ecprivkey, bufferToBigInt(chainIDBuffer)) - st.ok(sigBuffer.r.equals(expectedSigR)) - st.ok(sigBuffer.s.equals(expectedSigS)) + const sigBuffer = ecsign(echash, ecprivkey, bytesToBigInt(chainIDBuffer)) + st.deepEquals(sigBuffer.r, expectedSigR) + st.deepEquals(sigBuffer.s, expectedSigS) st.equal(sigBuffer.v, expectedSigV) st.end() @@ -100,57 +87,57 @@ tape('ecsign', function (t) { tape('ecrecover', function (t) { t.test('should recover a public key', function (st) { - const r = Buffer.from('99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1abe9', 'hex') - const s = Buffer.from('129ff05af364204442bdb53ab6f18a99ab48acc9326fa689f228040429e3ca66', 'hex') + const r = hexToBytes('99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1abe9') + const s = hexToBytes('129ff05af364204442bdb53ab6f18a99ab48acc9326fa689f228040429e3ca66') const v = BigInt(27) const pubkey = ecrecover(echash, v, r, s) - st.ok(pubkey.equals(privateToPublic(ecprivkey))) + st.deepEquals(pubkey, privateToPublic(ecprivkey)) st.end() }) t.test('should recover a public key (chainId = 3)', function (st) { - const r = Buffer.from('99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1abe9', 'hex') - const s = Buffer.from('129ff05af364204442bdb53ab6f18a99ab48acc9326fa689f228040429e3ca66', 'hex') + const r = hexToBytes('99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1abe9') + const s = hexToBytes('129ff05af364204442bdb53ab6f18a99ab48acc9326fa689f228040429e3ca66') const v = BigInt(41) const pubkey = ecrecover(echash, v, r, s, chainId) - st.ok(pubkey.equals(privateToPublic(ecprivkey))) + st.deepEquals(pubkey, privateToPublic(ecprivkey)) st.end() }) t.test('should recover a public key (chainId = 150)', function (st) { const chainId = BigInt(150) - const r = Buffer.from('99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1abe9', 'hex') - const s = Buffer.from('129ff05af364204442bdb53ab6f18a99ab48acc9326fa689f228040429e3ca66', 'hex') + const r = hexToBytes('99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1abe9') + const s = hexToBytes('129ff05af364204442bdb53ab6f18a99ab48acc9326fa689f228040429e3ca66') const v = BigInt(chainId * BigInt(2) + BigInt(35)) const pubkey = ecrecover(echash, v, r, s, chainId) - st.ok(pubkey.equals(privateToPublic(ecprivkey))) + st.deepEquals(pubkey, privateToPublic(ecprivkey)) st.end() }) t.test('should recover a public key (v = 0)', function (st) { - const r = Buffer.from('99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1abe9', 'hex') - const s = Buffer.from('129ff05af364204442bdb53ab6f18a99ab48acc9326fa689f228040429e3ca66', 'hex') + const r = hexToBytes('99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1abe9') + const s = hexToBytes('129ff05af364204442bdb53ab6f18a99ab48acc9326fa689f228040429e3ca66') const v = BigInt(0) const pubkey = ecrecover(echash, v, r, s) - st.ok(pubkey.equals(privateToPublic(ecprivkey))) + st.deepEquals(pubkey, privateToPublic(ecprivkey)) st.end() }) t.test('should fail on an invalid signature (v = 21)', function (st) { - const r = Buffer.from('99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1abe9', 'hex') - const s = Buffer.from('129ff05af364204442bdb53ab6f18a99ab48acc9326fa689f228040429e3ca66', 'hex') + const r = hexToBytes('99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1abe9') + const s = hexToBytes('129ff05af364204442bdb53ab6f18a99ab48acc9326fa689f228040429e3ca66') st.throws(function () { ecrecover(echash, BigInt(21), r, s) }) st.end() }) t.test('should fail on an invalid signature (v = 29)', function (st) { - const r = Buffer.from('99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1abe9', 'hex') - const s = Buffer.from('129ff05af364204442bdb53ab6f18a99ab48acc9326fa689f228040429e3ca66', 'hex') + const r = hexToBytes('99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1abe9') + const s = hexToBytes('129ff05af364204442bdb53ab6f18a99ab48acc9326fa689f228040429e3ca66') st.throws(function () { ecrecover(echash, BigInt(29), r, s) }) st.end() }) t.test('should fail on an invalid signature (swapped points)', function (st) { - const r = Buffer.from('99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1abe9', 'hex') - const s = Buffer.from('129ff05af364204442bdb53ab6f18a99ab48acc9326fa689f228040429e3ca66', 'hex') + const r = hexToBytes('99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1abe9') + const s = hexToBytes('129ff05af364204442bdb53ab6f18a99ab48acc9326fa689f228040429e3ca66') st.throws(function () { ecrecover(echash, BigInt(27), s, r) }) @@ -171,41 +158,33 @@ tape('ecrecover', function (t) { s: '0x4b8e02b96b94064a5aa2f8d72bd0040616ba8e482a5dd96422e38c9a4611f8d5' } */ - const senderPubKey = Buffer.from( - '78988201fbceed086cfca7b64e382d08d0bd776898731443d2907c097745b7324c54f522087f5964412cddba019f192de0fd57a0ffa63f098c2b200e53594b15', - 'hex' - ) - const msgHash = Buffer.from( - '8ae8cb685a7a9f29494b07b287c3f6a103b73fa178419d10d1184861a40f6afe', - 'hex' + const senderPubKey = hexToBytes( + '78988201fbceed086cfca7b64e382d08d0bd776898731443d2907c097745b7324c54f522087f5964412cddba019f192de0fd57a0ffa63f098c2b200e53594b15' ) + const msgHash = hexToBytes('8ae8cb685a7a9f29494b07b287c3f6a103b73fa178419d10d1184861a40f6afe') - const r = Buffer.from('ec212841e0b7aaffc3b3e33a08adf32fa07159e856ef23db85175a4f6d71dc0f', 'hex') - const s = Buffer.from('4b8e02b96b94064a5aa2f8d72bd0040616ba8e482a5dd96422e38c9a4611f8d5', 'hex') + const r = hexToBytes('ec212841e0b7aaffc3b3e33a08adf32fa07159e856ef23db85175a4f6d71dc0f') + const s = hexToBytes('4b8e02b96b94064a5aa2f8d72bd0040616ba8e482a5dd96422e38c9a4611f8d5') const v = BigInt('68361967398315796') const chainID = BigInt('34180983699157880') const sender = ecrecover(msgHash, v, r, s, chainID) - st.ok(sender.equals(senderPubKey), 'sender pubkey correct (Buffer)') + st.deepEquals(sender, senderPubKey, 'sender pubkey correct (Buffer)') st.end() }) }) tape('hashPersonalMessage', function (t) { t.test('should produce a deterministic hash', function (st) { - const h = hashPersonalMessage(Buffer.from('Hello world')) - st.ok( - h.equals( - Buffer.from('8144a6fa26be252b86456491fbcd43c1de7e022241845ffea1c3df066f7cfede', 'hex') - ) - ) + const h = hashPersonalMessage(utf8ToBytes('Hello world')) + st.deepEquals(h, hexToBytes('8144a6fa26be252b86456491fbcd43c1de7e022241845ffea1c3df066f7cfede')) st.end() }) - t.test('should throw if input is not a buffer', function (st) { + t.test('should throw if input is not a Uint8Array', function (st) { try { - hashPersonalMessage(([0, 1, 2, 3, 4]) as Buffer) + hashPersonalMessage(([0, 1, 2, 3, 4]) as Uint8Array) } catch (err: any) { - st.ok(err.message.includes('This method only supports Buffer')) + st.ok(err.message.includes('This method only supports Uint8Array')) } st.end() }) @@ -213,26 +192,26 @@ tape('hashPersonalMessage', function (t) { tape('isValidSignature', function (t) { t.test('should fail on an invalid signature (shorter r))', function (st) { - const r = Buffer.from('99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1ab', 'hex') - const s = Buffer.from('129ff05af364204442bdb53ab6f18a99ab48acc9326fa689f228040429e3ca66', 'hex') + const r = hexToBytes('99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1ab') + const s = hexToBytes('129ff05af364204442bdb53ab6f18a99ab48acc9326fa689f228040429e3ca66') st.notOk(isValidSignature(BigInt(27), r, s)) st.end() }) t.test('should fail on an invalid signature (shorter s))', function (st) { - const r = Buffer.from('99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1abe9', 'hex') - const s = Buffer.from('129ff05af364204442bdb53ab6f18a99ab48acc9326fa689f228040429e3ca', 'hex') + const r = hexToBytes('99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1abe9') + const s = hexToBytes('129ff05af364204442bdb53ab6f18a99ab48acc9326fa689f228040429e3ca') st.notOk(isValidSignature(BigInt(27), r, s)) st.end() }) t.test('should fail on an invalid signature (v = 21)', function (st) { - const r = Buffer.from('99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1abe9', 'hex') - const s = Buffer.from('129ff05af364204442bdb53ab6f18a99ab48acc9326fa689f228040429e3ca66', 'hex') + const r = hexToBytes('99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1abe9') + const s = hexToBytes('129ff05af364204442bdb53ab6f18a99ab48acc9326fa689f228040429e3ca66') st.notOk(isValidSignature(BigInt(21), r, s)) st.end() }) t.test('should fail on an invalid signature (v = 29)', function (st) { - const r = Buffer.from('99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1abe9', 'hex') - const s = Buffer.from('129ff05af364204442bdb53ab6f18a99ab48acc9326fa689f228040429e3ca66', 'hex') + const r = hexToBytes('99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1abe9') + const s = hexToBytes('129ff05af364204442bdb53ab6f18a99ab48acc9326fa689f228040429e3ca66') st.notOk(isValidSignature(BigInt(29), r, s)) st.end() }) @@ -241,8 +220,8 @@ tape('isValidSignature', function (t) { '0x7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0' ) - const r = Buffer.from('99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1abe9', 'hex') - const s = bigIntToBuffer(SECP256K1_N_DIV_2 + BigInt(1)) + const r = hexToBytes('99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1abe9') + const s = bigIntToBytes(SECP256K1_N_DIV_2 + BigInt(1)) const v = BigInt(27) st.notOk(isValidSignature(v, r, s, true)) @@ -253,44 +232,44 @@ tape('isValidSignature', function (t) { '0x7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0' ) - const r = Buffer.from('99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1abe9', 'hex') - const s = bigIntToBuffer(SECP256K1_N_DIV_2 + BigInt(1)) + const r = hexToBytes('99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1abe9') + const s = bigIntToBytes(SECP256K1_N_DIV_2 + BigInt(1)) const v = BigInt(27) st.ok(isValidSignature(v, r, s, false)) st.end() }) t.test('should work otherwise', function (st) { - const r = Buffer.from('99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1abe9', 'hex') - const s = Buffer.from('129ff05af364204442bdb53ab6f18a99ab48acc9326fa689f228040429e3ca66', 'hex') + const r = hexToBytes('99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1abe9') + const s = hexToBytes('129ff05af364204442bdb53ab6f18a99ab48acc9326fa689f228040429e3ca66') const v = BigInt(27) st.ok(isValidSignature(v, r, s)) st.end() }) t.test('should work otherwise (v=0)', function (st) { - const r = Buffer.from('99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1abe9', 'hex') - const s = Buffer.from('129ff05af364204442bdb53ab6f18a99ab48acc9326fa689f228040429e3ca66', 'hex') + const r = hexToBytes('99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1abe9') + const s = hexToBytes('129ff05af364204442bdb53ab6f18a99ab48acc9326fa689f228040429e3ca66') const v = BigInt(0) st.ok(isValidSignature(v, r, s)) st.end() }) t.test('should work otherwise (v=1)', function (st) { - const r = Buffer.from('99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1abe9', 'hex') - const s = Buffer.from('129ff05af364204442bdb53ab6f18a99ab48acc9326fa689f228040429e3ca66', 'hex') + const r = hexToBytes('99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1abe9') + const s = hexToBytes('129ff05af364204442bdb53ab6f18a99ab48acc9326fa689f228040429e3ca66') const v = BigInt(1) st.ok(isValidSignature(v, r, s)) st.end() }) t.test('should work otherwise (chainId=3)', function (st) { - const r = Buffer.from('99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1abe9', 'hex') - const s = Buffer.from('129ff05af364204442bdb53ab6f18a99ab48acc9326fa689f228040429e3ca66', 'hex') + const r = hexToBytes('99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1abe9') + const s = hexToBytes('129ff05af364204442bdb53ab6f18a99ab48acc9326fa689f228040429e3ca66') const v = BigInt(41) st.ok(isValidSignature(v, r, s, false, chainId)) st.end() }) t.test('should work otherwise (chainId=150)', function (st) { const chainId = BigInt(150) - const r = Buffer.from('99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1abe9', 'hex') - const s = Buffer.from('129ff05af364204442bdb53ab6f18a99ab48acc9326fa689f228040429e3ca66', 'hex') + const r = hexToBytes('99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1abe9') + const s = hexToBytes('129ff05af364204442bdb53ab6f18a99ab48acc9326fa689f228040429e3ca66') const v = BigInt(chainId * BigInt(2) + BigInt(35)) st.ok(isValidSignature(v, r, s, false, chainId)) st.end() @@ -298,8 +277,8 @@ tape('isValidSignature', function (t) { }) tape('message sig', function (t) { - const r = Buffer.from('99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1abe9', 'hex') - const s = Buffer.from('129ff05af364204442bdb53ab6f18a99ab48acc9326fa689f228040429e3ca66', 'hex') + const r = hexToBytes('99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1abe9') + const s = hexToBytes('129ff05af364204442bdb53ab6f18a99ab48acc9326fa689f228040429e3ca66') t.test('should return hex strings that the RPC can use', function (st) { const sig = @@ -382,7 +361,7 @@ tape('message sig', function (t) { '0x99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1abe9129ff05af364204442bdb53ab6f18a99ab48acc9326fa689f228040429e3ca66f2ded8deec6714' const chainID = BigInt('34180983699157880') const v = BigInt('68361967398315796') - st.equal(toRpcSig(v, r, s, chainID), sig) + st.deepEquals(toRpcSig(v, r, s, chainID), sig) st.end() } ) diff --git a/packages/util/test/ssz.spec.ts b/packages/util/test/ssz.spec.ts index 695e800002..ebd8b233d3 100644 --- a/packages/util/test/ssz.spec.ts +++ b/packages/util/test/ssz.spec.ts @@ -1,3 +1,4 @@ +import { bytesToHex, hexToBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' import { Withdrawal, ssz } from '../src' @@ -5,49 +6,49 @@ const withdrawalsData = [ { index: BigInt(0), validatorIndex: BigInt(65535), - address: Buffer.from('0000000000000000000000000000000000000000', 'hex'), + address: hexToBytes('0000000000000000000000000000000000000000'), amount: BigInt('0'), }, { index: BigInt(1), validatorIndex: BigInt(65536), - address: Buffer.from('0100000000000000000000000000000000000000', 'hex'), + address: hexToBytes('0100000000000000000000000000000000000000'), amount: BigInt('04523128485832663883'), }, { index: BigInt(2), validatorIndex: BigInt(65537), - address: Buffer.from('0200000000000000000000000000000000000000', 'hex'), + address: hexToBytes('0200000000000000000000000000000000000000'), amount: BigInt('09046256971665327767'), }, { index: BigInt(4), validatorIndex: BigInt(65538), - address: Buffer.from('0300000000000000000000000000000000000000', 'hex'), + address: hexToBytes('0300000000000000000000000000000000000000'), amount: BigInt('13569385457497991651'), }, { index: BigInt(4), validatorIndex: BigInt(65539), - address: Buffer.from('0400000000000000000000000000000000000000', 'hex'), + address: hexToBytes('0400000000000000000000000000000000000000'), amount: BigInt('18446744073709551615'), }, { index: BigInt(5), validatorIndex: BigInt(65540), - address: Buffer.from('0500000000000000000000000000000000000000', 'hex'), + address: hexToBytes('0500000000000000000000000000000000000000'), amount: BigInt('02261564242916331941'), }, { index: BigInt(6), validatorIndex: BigInt(65541), - address: Buffer.from('0600000000000000000000000000000000000000', 'hex'), + address: hexToBytes('0600000000000000000000000000000000000000'), amount: BigInt('02713877091499598330'), }, { index: BigInt(7), validatorIndex: BigInt(65542), - address: Buffer.from('0700000000000000000000000000000000000000', 'hex'), + address: hexToBytes('0700000000000000000000000000000000000000'), amount: BigInt('03166189940082864718'), }, ] @@ -56,16 +57,12 @@ tape('ssz', (t) => { t.test('withdrawals', (st) => { const withdrawals = withdrawalsData.map((wt) => Withdrawal.fromWithdrawalData(wt)) const withdrawalsValue = withdrawals.map((wt) => wt.toValue()) - const sszValues = ssz.Withdrawals.toViewDU(withdrawalsData) - .toValue() - .map((wt) => { - wt.address = Buffer.from(wt.address) - return wt - }) + const sszValues = ssz.Withdrawals.toViewDU(withdrawalsData).toValue() + st.deepEqual(sszValues, withdrawalsValue, 'sszValues should be same as withdrawalsValue') const withdrawalsRoot = ssz.Withdrawals.hashTreeRoot(withdrawalsValue) st.equal( - Buffer.from(withdrawalsRoot).toString('hex'), + bytesToHex(withdrawalsRoot), 'bd97f65e513f870484e85927510acb291fcfb3e593c05ab7f21f206921264946', 'ssz root should match' ) @@ -77,7 +74,7 @@ tape('ssz', (t) => { { index: BigInt('17107150653359250726'), validatorIndex: BigInt('1906681273455760070'), - address: Buffer.from('02ab1379b6334b58df82c85d50ff1214663cba20', 'hex'), + address: hexToBytes('02ab1379b6334b58df82c85d50ff1214663cba20'), amount: BigInt('5055030296454530815'), }, ] @@ -85,7 +82,7 @@ tape('ssz', (t) => { t.test('match spec v1.3.0-rc.1', (st) => { const withdrawalsRoot = ssz.Withdrawal.hashTreeRoot(specWithdrawals[0]) st.equal( - Buffer.from(withdrawalsRoot).toString('hex'), + bytesToHex(withdrawalsRoot), 'ed9cec6fb8ee22b146059d02c38940cca1dd22a00d0132b000999b983fceff95', 'ssz root should match' ) diff --git a/packages/util/test/types.spec.ts b/packages/util/test/types.spec.ts index fe1988586a..cf8ef00ddb 100644 --- a/packages/util/test/types.spec.ts +++ b/packages/util/test/types.spec.ts @@ -1,14 +1,14 @@ +import { bytesToHex } from 'ethereum-cryptography/utils' import * as tape from 'tape' import { TypeOutput, - bigIntToBuffer, + bigIntToBytes, bigIntToHex, - bufferToBigInt, - bufferToHex, - intToBuffer, + bytesToBigInt, + intToBytes, intToHex, - toBuffer, + toBytes, toType, } from '../src' @@ -16,11 +16,11 @@ tape('toType', function (t) { t.test('from null and undefined', function (st) { st.equal(toType(null, TypeOutput.Number), null) st.equal(toType(null, TypeOutput.BigInt), null) - st.equal(toType(null, TypeOutput.Buffer), null) + st.equal(toType(null, TypeOutput.Uint8Array), null) st.equal(toType(null, TypeOutput.PrefixedHexString), null) st.equal(toType(undefined, TypeOutput.Number), undefined) st.equal(toType(undefined, TypeOutput.BigInt), undefined) - st.equal(toType(undefined, TypeOutput.Buffer), undefined) + st.equal(toType(undefined, TypeOutput.Uint8Array), undefined) st.equal(toType(undefined, TypeOutput.PrefixedHexString), undefined) st.end() }) @@ -36,14 +36,14 @@ tape('toType', function (t) { st.equal(result, BigInt(num)) st.end() }) - st.test('should convert to Buffer', function (st) { - const result = toType(num, TypeOutput.Buffer) - st.ok(result.equals(intToBuffer(num))) + st.test('should convert to Uint8Array', function (st) { + const result = toType(num, TypeOutput.Uint8Array) + st.deepEquals(result, intToBytes(num)) st.end() }) st.test('should convert to PrefixedHexString', function (st) { const result = toType(num, TypeOutput.PrefixedHexString) - st.strictEqual(result, bufferToHex(bigIntToBuffer(BigInt(num)))) + st.strictEqual(result, bytesToHex(bigIntToBytes(BigInt(num)))) st.end() }) st.test('should throw an error if greater than MAX_SAFE_INTEGER', function (st) { @@ -66,14 +66,14 @@ tape('toType', function (t) { st.equal(result, num) st.end() }) - st.test('should convert to Buffer', function (st) { - const result = toType(num, TypeOutput.Buffer) - st.ok(result.equals(bigIntToBuffer(num))) + st.test('should convert to Uint8Array', function (st) { + const result = toType(num, TypeOutput.Uint8Array) + st.deepEquals(result, bigIntToBytes(num)) st.end() }) st.test('should convert to PrefixedHexString', function (st) { const result = toType(num, TypeOutput.PrefixedHexString) - st.strictEqual(result, bufferToHex(bigIntToBuffer(num))) + st.strictEqual(result, bytesToHex(bigIntToBytes(num))) st.end() }) st.test( @@ -87,26 +87,26 @@ tape('toType', function (t) { } ) }) - t.test('from Buffer', function (st) { - const num = intToBuffer(1000) + t.test('from Uint8Array', function (st) { + const num = intToBytes(1000) st.test('should convert to Number', function (st) { const result = toType(num, TypeOutput.Number) - st.ok(intToBuffer(result).equals(num)) + st.deepEquals(intToBytes(result), num) st.end() }) st.test('should convert to BigInt', function (st) { const result = toType(num, TypeOutput.BigInt) - st.equal(result, bufferToBigInt(num)) + st.equal(result, bytesToBigInt(num)) st.end() }) - st.test('should convert to Buffer', function (st) { - const result = toType(num, TypeOutput.Buffer) - st.ok(result.equals(num)) + st.test('should convert to Uint8Array', function (st) { + const result = toType(num, TypeOutput.Uint8Array) + st.deepEquals(result, num) st.end() }) st.test('should convert to PrefixedHexString', function (st) { const result = toType(num, TypeOutput.PrefixedHexString) - st.strictEqual(result, bufferToHex(num)) + st.strictEqual(result, bytesToHex(num)) st.end() }) }) @@ -122,9 +122,9 @@ tape('toType', function (t) { st.strictEqual(bigIntToHex(result), num) st.end() }) - st.test('should convert to Buffer', function (st) { - const result = toType(num, TypeOutput.Buffer) - st.ok(result.equals(toBuffer(num))) + st.test('should convert to Uint8Array', function (st) { + const result = toType(num, TypeOutput.Uint8Array) + st.deepEquals(result, toBytes(num)) st.end() }) st.test('should throw an error if is not 0x-prefixed', function (st) { diff --git a/packages/util/test/withdrawal.spec.ts b/packages/util/test/withdrawal.spec.ts index a521255b87..ee8f6849c6 100644 --- a/packages/util/test/withdrawal.spec.ts +++ b/packages/util/test/withdrawal.spec.ts @@ -1,9 +1,10 @@ import { decode, encode } from '@ethereumjs/rlp' +import { bytesToHex, hexToBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' -import { Withdrawal, bigIntToHex, intToHex } from '../src' +import { Withdrawal, bigIntToHex, bytesToPrefixedHexString, intToHex } from '../src' -import type { WithdrawalBuffer } from '../src' +import type { WithdrawalBytes } from '../src' const withdrawalsVector = [ { @@ -66,33 +67,31 @@ const gethWithdrawals8BlockRlp = tape('Withdrawal', (t) => { // gethWithdrawals8Rlp is rlp encoded block with withdrawals in the 4th element of the top array - const gethWithdrawalsBuffer = decode(Buffer.from(gethWithdrawals8BlockRlp, 'hex'))[3]! - const gethWithdrawalsRlp = Buffer.from(encode(gethWithdrawalsBuffer)).toString('hex') - t.test('fromWithdrawalData and toBufferArray', (st) => { + const gethWithdrawalsBuffer = decode(hexToBytes(gethWithdrawals8BlockRlp))[3]! + const gethWithdrawalsRlp = bytesToHex(encode(gethWithdrawalsBuffer)) + t.test('fromWithdrawalData and toBytesArray', (st) => { const withdrawals = withdrawalsGethVector.map(Withdrawal.fromWithdrawalData) - const withdrawalsToBufferArr = withdrawals.map((wt) => wt.raw()) - const withdrawalsToRlp = Buffer.from(encode(withdrawalsToBufferArr)).toString('hex') + const withdrawalstoBytesArr = withdrawals.map((wt) => wt.raw()) + const withdrawalsToRlp = bytesToHex(encode(withdrawalstoBytesArr)) st.equal(gethWithdrawalsRlp, withdrawalsToRlp, 'The withdrawals to buffer should match') st.end() }) - t.test('toBufferArray from withdrawalData', (st) => { - const withdrawalsDataToBufferArr = withdrawalsGethVector.map(Withdrawal.toBufferArray) - const withdrawalsDataToRlp = Buffer.from(encode(withdrawalsDataToBufferArr)).toString('hex') + t.test('toBytesArray from withdrawalData', (st) => { + const withdrawalsDatatoBytesArr = withdrawalsGethVector.map(Withdrawal.toBytesArray) + const withdrawalsDataToRlp = bytesToHex(encode(withdrawalsDatatoBytesArr)) st.equal(gethWithdrawalsRlp, withdrawalsDataToRlp, 'The withdrawals to buffer should match') st.end() }) t.test('fromValuesArray, toJSON and toValue', (st) => { - const withdrawals = (gethWithdrawalsBuffer as WithdrawalBuffer[]).map( - Withdrawal.fromValuesArray - ) + const withdrawals = (gethWithdrawalsBuffer as WithdrawalBytes[]).map(Withdrawal.fromValuesArray) const withdrawalsJson = withdrawals.map((wt) => wt.toJSON()) st.deepEqual(withdrawalsGethVector, withdrawalsJson, 'Withdrawals json should match') const withdrawalsValue = withdrawals.map((wt) => wt.toValue()) st.deepEqual( - withdrawalsValue.map((wt) => `0x${wt.address.toString('hex')}`), + withdrawalsValue.map((wt) => bytesToPrefixedHexString(wt.address)), withdrawalsJson.map((wt) => wt.address) ) st.end() diff --git a/packages/vm/benchmarks/mockchain.ts b/packages/vm/benchmarks/mockchain.ts index 51340b5e1c..fb413978d1 100644 --- a/packages/vm/benchmarks/mockchain.ts +++ b/packages/vm/benchmarks/mockchain.ts @@ -17,7 +17,7 @@ export class Mockchain { } } - putBlockHash(num: bigint, hash: Buffer): void { + putBlockHash(num: bigint, hash: Uint8Array): void { this._hashes[num.toString()] = hash } } diff --git a/packages/vm/benchmarks/util.ts b/packages/vm/benchmarks/util.ts index 923b1c7fcc..e52f04a651 100644 --- a/packages/vm/benchmarks/util.ts +++ b/packages/vm/benchmarks/util.ts @@ -1,4 +1,4 @@ -import { Account, Address, toBuffer } from '@ethereumjs/util' +import { Account, Address, equalsBytes, toBytes } from '@ethereumjs/util' import { Common } from '@ethereumjs/common' import { Block } from '@ethereumjs/block' import { StateManager, DefaultStateManager } from '@ethereumjs/statemanager' @@ -29,18 +29,18 @@ export async function getPreState( const state = new DefaultStateManager() await state.checkpoint() for (const k in pre) { - const address = new Address(toBuffer(k)) + const address = new Address(toBytes(k)) const { nonce, balance, code, storage } = pre[k] const account = new Account(BigInt(nonce), BigInt(balance)) await state.putAccount(address, account) - await state.putContractCode(address, toBuffer(code)) + await state.putContractCode(address, toBytes(code)) for (const sk in storage) { const sv = storage[sk] - const valueBuffer = toBuffer(sv) + const valueBytes = toBytes(sv) // verify if this value buffer is not a zero buffer. if so, we should not write it... - const zeroBufferEquivalent = Buffer.alloc(valueBuffer.length, 0) - if (!zeroBufferEquivalent.equals(valueBuffer)) { - await state.putContractStorage(address, toBuffer(sk), toBuffer(sv)) + const zeroBytesEquivalent = new Uint8Array(valueBytes.length) + if (!equalsBytes(zeroBytesEquivalent, valueBytes)) { + await state.putContractStorage(address, toBytes(sk), toBytes(sv)) } } } @@ -52,7 +52,7 @@ export function getBlockchain(blockhashes: any): Mockchain { let mockchain = new Mockchain() for (const blockNum in blockhashes) { const hash = blockhashes[blockNum] - mockchain.putBlockHash(BigInt(blockNum), toBuffer(hash)) + mockchain.putBlockHash(BigInt(blockNum), toBytes(hash)) } return mockchain } @@ -60,7 +60,7 @@ export function getBlockchain(blockhashes: any): Mockchain { export const verifyResult = (block: Block, result: RunBlockResult) => { // verify the receipts root, the logs bloom and the gas used after block execution, // throw if any of these is not the expected value - if (result.receiptsRoot && !result.receiptsRoot.equals(block.header.receiptTrie)) { + if (result.receiptsRoot && !equalsBytes(result.receiptsRoot, block.header.receiptTrie)) { // there's something wrong here with the receipts trie. // if block has receipt data we can check against the expected result of the block // and the reported data of the VM in order to isolate the problem @@ -86,7 +86,7 @@ export const verifyResult = (block: Block, result: RunBlockResult) => { } throw new Error('invalid receiptTrie') } - if (!result.logsBloom.equals(block.header.logsBloom)) { + if (!equalsBytes(result.logsBloom, block.header.logsBloom)) { throw new Error('invalid logsBloom') } if (block.header.gasUsed !== result.gasUsed) { diff --git a/packages/vm/examples/helpers/account-utils.ts b/packages/vm/examples/helpers/account-utils.ts index ce0861be87..9d806f5746 100644 --- a/packages/vm/examples/helpers/account-utils.ts +++ b/packages/vm/examples/helpers/account-utils.ts @@ -17,7 +17,7 @@ export const insertAccount = async (vm: VM, address: Address) => { await vm.stateManager.putAccount(address, account) } -export const getAccountNonce = async (vm: VM, accountPrivateKey: Buffer) => { +export const getAccountNonce = async (vm: VM, accountPrivateKey: Uint8Array) => { const address = Address.fromPrivateKey(accountPrivateKey) const account = await vm.stateManager.getAccount(address) return account.nonce diff --git a/packages/vm/examples/run-blockchain.ts b/packages/vm/examples/run-blockchain.ts index 90e8f9a205..249d174897 100644 --- a/packages/vm/examples/run-blockchain.ts +++ b/packages/vm/examples/run-blockchain.ts @@ -6,12 +6,19 @@ // 4. Puts the blocks from ../utils/blockchain-mock-data "blocks" attribute into the Blockchain // 5. Runs the Blockchain on the VM. -import { Account, Address, toBuffer, setLengthLeft } from '@ethereumjs/util' +import { + Account, + Address, + toBytes, + setLengthLeft, + bytesToPrefixedHexString, +} from '@ethereumjs/util' import { Block } from '@ethereumjs/block' import { Blockchain } from '@ethereumjs/blockchain' import { Common, ConsensusType } from '@ethereumjs/common' import { VM } from '../' import { testData } from './helpers/blockchain-mock-data' +import { hexToBytes } from 'ethereum-cryptography/utils' async function main() { const common = new Common({ chain: 1, hardfork: testData.network.toLowerCase() }) @@ -43,7 +50,7 @@ async function main() { const blockchainHead = await vm.blockchain.getIteratorHead!() console.log('--- Finished processing the Blockchain ---') - console.log('New head:', '0x' + blockchainHead.hash().toString('hex')) + console.log('New head:', bytesToPrefixedHexString(blockchainHead.hash())) console.log('Expected:', testData.lastblockhash) } @@ -53,17 +60,17 @@ async function setupPreConditions(vm: VM, data: typeof testData) { for (const [addr, acct] of Object.entries(data.pre)) { const { nonce, balance, storage, code } = acct - const address = new Address(Buffer.from(addr.slice(2), 'hex')) + const address = new Address(hexToBytes(addr.slice(2))) const account = Account.fromAccountData({ nonce, balance }) await vm.stateManager.putAccount(address, account) for (const [key, val] of Object.entries(storage)) { - const storageKey = setLengthLeft(Buffer.from(key, 'hex'), 32) - const storageVal = Buffer.from(val as string, 'hex') + const storageKey = setLengthLeft(hexToBytes(key), 32) + const storageVal = hexToBytes(val as string) await vm.stateManager.putContractStorage(address, storageKey, storageVal) } - const codeBuf = Buffer.from(code.slice(2), 'hex') + const codeBuf = hexToBytes(code.slice(2)) await vm.stateManager.putContractCode(address, codeBuf) } @@ -72,7 +79,7 @@ async function setupPreConditions(vm: VM, data: typeof testData) { async function putBlocks(blockchain: Blockchain, common: Common, data: typeof testData) { for (const blockData of data.blocks) { - const blockRlp = toBuffer(blockData.rlp) + const blockRlp = toBytes(blockData.rlp) const block = Block.fromRLPSerializedBlock(blockRlp, { common }) await blockchain.putBlock(block) } diff --git a/packages/vm/examples/run-solidity-contract.ts b/packages/vm/examples/run-solidity-contract.ts index b33409dbbd..1d45d84372 100644 --- a/packages/vm/examples/run-solidity-contract.ts +++ b/packages/vm/examples/run-solidity-contract.ts @@ -4,17 +4,18 @@ import { defaultAbiCoder as AbiCoder, Interface } from '@ethersproject/abi' import { Address } from '@ethereumjs/util' import { Chain, Common, Hardfork } from '@ethereumjs/common' import { Transaction } from '@ethereumjs/tx' -import { VM } from '..' +import { VM } from '@ethereumjs/vm' import { buildTransaction, encodeDeployment, encodeFunction } from './helpers/tx-builder' import { getAccountNonce, insertAccount } from './helpers/account-utils' import { Block } from '@ethereumjs/block' +import { bytesToHex, hexToBytes, utf8ToBytes } from 'ethereum-cryptography/utils' const solc = require('solc') const INITIAL_GREETING = 'Hello, World!' const SECOND_GREETING = 'Hola, Mundo!' const common = new Common({ chain: Chain.Rinkeby, hardfork: Hardfork.Istanbul }) -const block = Block.fromBlockData({ header: { extraData: Buffer.alloc(97) } }, { common }) +const block = Block.fromBlockData({ header: { extraData: new Uint8Array(97) } }, { common }) /** * This function creates the input for the Solidity compiler. @@ -85,13 +86,14 @@ function getGreeterDeploymentBytecode(solcOutput: any): any { async function deployContract( vm: VM, - senderPrivateKey: Buffer, - deploymentBytecode: Buffer, + senderPrivateKey: Uint8Array, + deploymentBytecode: string, greeting: string ): Promise
{ // Contracts are deployed by sending their deployment bytecode to the address 0 // The contract params should be abi-encoded and appended to the deployment bytecode. - const data = encodeDeployment(deploymentBytecode.toString('hex'), { + + const data = encodeDeployment(deploymentBytecode, { types: ['string'], values: [greeting], }) @@ -113,7 +115,7 @@ async function deployContract( async function setGreeting( vm: VM, - senderPrivateKey: Buffer, + senderPrivateKey: Uint8Array, contractAddress: Address, greeting: string ) { @@ -144,7 +146,7 @@ async function getGreeting(vm: VM, contractAddress: Address, caller: Address) { to: contractAddress, caller: caller, origin: caller, // The tx.origin is also the caller here - data: Buffer.from(sigHash.slice(2), 'hex'), + data: hexToBytes(sigHash.slice(2)), block, }) @@ -158,10 +160,7 @@ async function getGreeting(vm: VM, contractAddress: Address, caller: Address) { } async function main() { - const accountPk = Buffer.from( - 'e331b6d69882b4cb4ea581d88e0b604039a3de5967688d3dcffdd2270c0fd109', - 'hex' - ) + const accountPk = hexToBytes('e331b6d69882b4cb4ea581d88e0b604039a3de5967688d3dcffdd2270c0fd109') const vm = await VM.create({ common }) const accountAddress = Address.fromPrivateKey(accountPk) @@ -215,8 +214,8 @@ async function main() { console.log('-------results-------') console.log('nonce: ' + createdAccount.nonce.toString()) console.log('balance in wei: ', createdAccount.balance.toString()) - console.log('storageRoot: 0x' + createdAccount.storageRoot.toString('hex')) - console.log('codeHash: 0x' + createdAccount.codeHash.toString('hex')) + console.log('storageRoot: 0x' + bytesToHex(createdAccount.storageRoot)) + console.log('codeHash: 0x' + bytesToHex(createdAccount.codeHash)) console.log('---------------------') console.log('Everything ran correctly!') diff --git a/packages/vm/src/bloom/index.ts b/packages/vm/src/bloom/index.ts index 78b8d529b8..e79272c3b2 100644 --- a/packages/vm/src/bloom/index.ts +++ b/packages/vm/src/bloom/index.ts @@ -4,12 +4,12 @@ import { keccak256 } from 'ethereum-cryptography/keccak' const BYTE_SIZE = 256 export class Bloom { - bitvector: Buffer + bitvector: Uint8Array /** * Represents a Bloom filter. */ - constructor(bitvector?: Buffer) { + constructor(bitvector?: Uint8Array) { if (!bitvector) { this.bitvector = zeros(BYTE_SIZE) } else { @@ -22,12 +22,12 @@ export class Bloom { * Adds an element to a bit vector of a 64 byte bloom filter. * @param e - The element to add */ - add(e: Buffer) { - e = Buffer.from(keccak256(e)) + add(e: Uint8Array) { + e = keccak256(e) const mask = 2047 // binary 11111111111 for (let i = 0; i < 3; i++) { - const first2bytes = e.readUInt16BE(i * 2) + const first2bytes = new DataView(e.buffer).getUint16(i * 2) const loc = mask & first2bytes const byteLoc = loc >> 3 const bitLoc = 1 << loc % 8 @@ -39,13 +39,13 @@ export class Bloom { * Checks if an element is in the bloom. * @param e - The element to check */ - check(e: Buffer): boolean { - e = Buffer.from(keccak256(e)) + check(e: Uint8Array): boolean { + e = keccak256(e) const mask = 2047 // binary 11111111111 let match = true for (let i = 0; i < 3 && match; i++) { - const first2bytes = e.readUInt16BE(i * 2) + const first2bytes = new DataView(e.buffer).getUint16(i * 2) const loc = mask & first2bytes const byteLoc = loc >> 3 const bitLoc = 1 << loc % 8 @@ -59,8 +59,8 @@ export class Bloom { * Checks if multiple topics are in a bloom. * @returns `true` if every topic is in the bloom */ - multiCheck(topics: Buffer[]): boolean { - return topics.every((t: Buffer) => this.check(t)) + multiCheck(topics: Uint8Array[]): boolean { + return topics.every((t: Uint8Array) => this.check(t)) } /** diff --git a/packages/vm/src/buildBlock.ts b/packages/vm/src/buildBlock.ts index b247a16a8f..f2a0ef6e56 100644 --- a/packages/vm/src/buildBlock.ts +++ b/packages/vm/src/buildBlock.ts @@ -3,7 +3,7 @@ import { ConsensusType } from '@ethereumjs/common' import { RLP } from '@ethereumjs/rlp' import { Trie } from '@ethereumjs/trie' import { BlobEIP4844Transaction } from '@ethereumjs/tx' -import { Address, GWEI_TO_WEI, TypeOutput, Withdrawal, toBuffer, toType } from '@ethereumjs/util' +import { Address, GWEI_TO_WEI, TypeOutput, Withdrawal, toBytes, toType } from '@ethereumjs/util' import { Bloom } from './bloom' import { calculateMinerReward, encodeReceipt, rewardAccount } from './runBlock' @@ -118,7 +118,7 @@ export class BlockBuilder { for (const [i, txResult] of this.transactionResults.entries()) { const tx = this.transactions[i] const encodedReceipt = encodeReceipt(txResult.receipt, tx.type) - await receiptTrie.put(Buffer.from(RLP.encode(i)), encodedReceipt) + await receiptTrie.put(RLP.encode(i), encodedReceipt) } return receiptTrie.root() } @@ -131,7 +131,7 @@ export class BlockBuilder { const reward = calculateMinerReward(minerReward, 0) const coinbase = this.headerData.coinbase !== undefined - ? new Address(toBuffer(this.headerData.coinbase)) + ? new Address(toBytes(this.headerData.coinbase)) : Address.zero() await rewardAccount(this.vm.eei, coinbase, reward) } @@ -192,7 +192,9 @@ export class BlockBuilder { throw new Error('block data gas limit reached') } - const parentHeader = await this.vm.blockchain.getBlock(this.headerData.parentHash! as Buffer) + const parentHeader = await this.vm.blockchain.getBlock( + this.headerData.parentHash! as Uint8Array + ) excessDataGas = calcExcessDataGas( parentHeader!.header, (tx as BlobEIP4844Transaction).blobs?.length ?? 0 @@ -271,9 +273,9 @@ export class BlockBuilder { if (this.vm._common.isActivatedEIP(4844)) { let parentHeader = null if (this.headerData.parentHash !== undefined) { - parentHeader = await this.vm.blockchain.getBlock(toBuffer(this.headerData.parentHash)) + parentHeader = await this.vm.blockchain.getBlock(toBytes(this.headerData.parentHash)) } - if (parentHeader !== null && parentHeader.header._common.isActivatedEIP(4844)) { + if (parentHeader !== null && parentHeader.header._common.isActivatedEIP(4844) === true) { // Compute total number of blobs in block const blobTxns = this.transactions.filter((tx) => tx instanceof BlobEIP4844Transaction) let newBlobs = 0 diff --git a/packages/vm/src/eei/eei.ts b/packages/vm/src/eei/eei.ts index cfcf2a3607..4b0dba48fb 100644 --- a/packages/vm/src/eei/eei.ts +++ b/packages/vm/src/eei/eei.ts @@ -1,4 +1,4 @@ -import { bufferToBigInt } from '@ethereumjs/util' +import { bytesToBigInt } from '@ethereumjs/util' import { VmState } from './vmState' @@ -8,7 +8,7 @@ import type { StateManager } from '@ethereumjs/statemanager' import type { Address } from '@ethereumjs/util' type Block = { - hash(): Buffer + hash(): Uint8Array } type Blockchain = { @@ -56,7 +56,7 @@ export class EEI extends VmState implements EEIInterface { * Returns code of an account. * @param address - Address of account */ - async getExternalCode(address: Address): Promise { + async getExternalCode(address: Address): Promise { return this.getContractCode(address) } @@ -66,7 +66,7 @@ export class EEI extends VmState implements EEIInterface { */ async getBlockHash(num: bigint): Promise { const block = await this._blockchain.getBlock(Number(num)) - return bufferToBigInt(block!.hash()) + return bytesToBigInt(block!.hash()) } /** @@ -75,7 +75,7 @@ export class EEI extends VmState implements EEIInterface { * @param key Storage key * @param value Storage value */ - async storageStore(address: Address, key: Buffer, value: Buffer): Promise { + async storageStore(address: Address, key: Uint8Array, value: Uint8Array): Promise { await this.putContractStorage(address, key, value) } @@ -85,7 +85,7 @@ export class EEI extends VmState implements EEIInterface { * @param key Storage key * @param original If true, return the original storage value (default: false) */ - async storageLoad(address: Address, key: Buffer, original = false): Promise { + async storageLoad(address: Address, key: Uint8Array, original = false): Promise { if (original) { return this.getOriginalContractStorage(address, key) } else { diff --git a/packages/vm/src/eei/vmState.ts b/packages/vm/src/eei/vmState.ts index 8e4f28293f..98cbadf9e2 100644 --- a/packages/vm/src/eei/vmState.ts +++ b/packages/vm/src/eei/vmState.ts @@ -1,7 +1,8 @@ import { Chain, Common, Hardfork } from '@ethereumjs/common' import { ripemdPrecompileAddress } from '@ethereumjs/evm/dist/precompiles' -import { Account, Address, toBuffer } from '@ethereumjs/util' +import { Account, Address, toBytes } from '@ethereumjs/util' import { debug as createDebugLogger } from 'debug' +import { bytesToHex, hexToBytes } from 'ethereum-cryptography/utils' import { Journaling } from './journaling' @@ -37,7 +38,7 @@ export class VmState implements EVMStateAccess { // to also include on access list generation protected _accessedStorageReverted: Map>[] - protected _originalStorageCache: Map> + protected _originalStorageCache: Map> protected readonly touchedJournal: Journaling @@ -116,7 +117,6 @@ export class VmState implements EVMStateAccess { this._accessedStorageReverted.push(lastItem) } } - await this._stateManager.revert() this.touchedJournal.revert(ripemdPrecompileAddress) @@ -154,19 +154,19 @@ export class VmState implements EVMStateAccess { this.touchAccount(address) } - async getContractCode(address: Address): Promise { + async getContractCode(address: Address): Promise { return this._stateManager.getContractCode(address) } - async putContractCode(address: Address, value: Buffer): Promise { + async putContractCode(address: Address, value: Uint8Array): Promise { return this._stateManager.putContractCode(address, value) } - async getContractStorage(address: Address, key: Buffer): Promise { + async getContractStorage(address: Address, key: Uint8Array): Promise { return this._stateManager.getContractStorage(address, key) } - async putContractStorage(address: Address, key: Buffer, value: Buffer) { + async putContractStorage(address: Address, key: Uint8Array, value: Uint8Array) { await this._stateManager.putContractStorage(address, key, value) this.touchAccount(address) } @@ -180,18 +180,18 @@ export class VmState implements EVMStateAccess { return this._stateManager.accountExists(address) } - async setStateRoot(stateRoot: Buffer): Promise { + async setStateRoot(stateRoot: Uint8Array): Promise { if (this._checkpointCount !== 0) { throw new Error('Cannot set state root with uncommitted checkpoints') } return this._stateManager.setStateRoot(stateRoot) } - async getStateRoot(): Promise { + async getStateRoot(): Promise { return this._stateManager.getStateRoot() } - async hasStateRoot(root: Buffer): Promise { + async hasStateRoot(root: Uint8Array): Promise { return this._stateManager.hasStateRoot(root) } @@ -203,7 +203,7 @@ export class VmState implements EVMStateAccess { * at the end of the tx. */ touchAccount(address: Address): void { - this.touchedJournal.addJournalItem(address.buf.toString('hex')) + this.touchedJournal.addJournalItem(address.toString().slice(2)) } /** @@ -256,11 +256,11 @@ export class VmState implements EVMStateAccess { const account = Account.fromAccountData({ balance }) await this.putAccount(addr, account) if (code !== undefined) { - await this.putContractCode(addr, toBuffer(code)) + await this.putContractCode(addr, toBytes(code)) } if (storage !== undefined) { for (const [key, value] of storage) { - await this.putContractStorage(addr, toBuffer(key), toBuffer(value)) + await this.putContractStorage(addr, toBytes(key), toBytes(value)) } } } @@ -276,7 +276,7 @@ export class VmState implements EVMStateAccess { if (this._common.gteHardfork(Hardfork.SpuriousDragon) === true) { const touchedArray = Array.from(this.touchedJournal.journal) for (const addressHex of touchedArray) { - const address = new Address(Buffer.from(addressHex, 'hex')) + const address = new Address(hexToBytes(addressHex)) const empty = await this.accountIsEmpty(address) if (empty) { await this._stateManager.deleteAccount(address) @@ -297,15 +297,18 @@ export class VmState implements EVMStateAccess { * @param address - Address of the account to get the storage for * @param key - Key in the account's storage to get the value for. Must be 32 bytes long. */ - protected async getOriginalContractStorage(address: Address, key: Buffer): Promise { + protected async getOriginalContractStorage( + address: Address, + key: Uint8Array + ): Promise { if (key.length !== 32) { throw new Error('Storage key must be 32 bytes long') } - const addressHex = address.buf.toString('hex') - const keyHex = key.toString('hex') + const addressHex = address.toString() + const keyHex = bytesToHex(key) - let map: Map + let map: Map if (!this._originalStorageCache.has(addressHex)) { map = new Map() this._originalStorageCache.set(addressHex, map) @@ -344,12 +347,12 @@ export class VmState implements EVMStateAccess { /** * Returns true if the address is warm in the current context - * @param address - The address (as a Buffer) to check + * @param address - The address (as a Uint8Array) to check */ - isWarmedAddress(address: Buffer): boolean { + isWarmedAddress(address: Uint8Array): boolean { for (let i = this._accessedStorage.length - 1; i >= 0; i--) { const currentMap = this._accessedStorage[i] - if (currentMap.has(address.toString('hex'))) { + if (currentMap.has(bytesToHex(address))) { return true } } @@ -358,10 +361,10 @@ export class VmState implements EVMStateAccess { /** * Add a warm address in the current context - * @param address - The address (as a Buffer) to check + * @param address - The address (as a Uint8Array) to check */ - addWarmedAddress(address: Buffer): void { - const key = address.toString('hex') + addWarmedAddress(address: Uint8Array): void { + const key = bytesToHex(address) const storageSet = this._accessedStorage[this._accessedStorage.length - 1].get(key) if (!storageSet) { const emptyStorage = new Set() @@ -371,12 +374,12 @@ export class VmState implements EVMStateAccess { /** * Returns true if the slot of the address is warm - * @param address - The address (as a Buffer) to check - * @param slot - The slot (as a Buffer) to check + * @param address - The address (as a Uint8Array) to check + * @param slot - The slot (as a Uint8Array) to check */ - isWarmedStorage(address: Buffer, slot: Buffer): boolean { - const addressKey = address.toString('hex') - const storageKey = slot.toString('hex') + isWarmedStorage(address: Uint8Array, slot: Uint8Array): boolean { + const addressKey = bytesToHex(address) + const storageKey = bytesToHex(slot) for (let i = this._accessedStorage.length - 1; i >= 0; i--) { const currentMap = this._accessedStorage[i] @@ -390,17 +393,17 @@ export class VmState implements EVMStateAccess { /** * Mark the storage slot in the address as warm in the current context - * @param address - The address (as a Buffer) to check - * @param slot - The slot (as a Buffer) to check + * @param address - The address (as a Uint8Array) to check + * @param slot - The slot (as a Uint8Array) to check */ - addWarmedStorage(address: Buffer, slot: Buffer): void { - const addressKey = address.toString('hex') + addWarmedStorage(address: Uint8Array, slot: Uint8Array): void { + const addressKey = bytesToHex(address) let storageSet = this._accessedStorage[this._accessedStorage.length - 1].get(addressKey) if (!storageSet) { storageSet = new Set() this._accessedStorage[this._accessedStorage.length - 1].set(addressKey, storageSet!) } - storageSet!.add(slot.toString('hex')) + storageSet!.add(bytesToHex(slot)) } /** diff --git a/packages/vm/src/runBlock.ts b/packages/vm/src/runBlock.ts index f4dfff2375..fcddca13ad 100644 --- a/packages/vm/src/runBlock.ts +++ b/packages/vm/src/runBlock.ts @@ -6,12 +6,15 @@ import { Account, Address, GWEI_TO_WEI, - bigIntToBuffer, - bufArrToArr, - intToBuffer, + bigIntToBytes, + bytesToHex, + concatBytesNoTypeCheck, + equalsBytes, + intToBytes, short, } from '@ethereumjs/util' import { debug as createDebugLogger } from 'debug' +import { hexToBytes } from 'ethereum-cryptography/utils' import { Bloom } from './bloom' import * as DAOConfig from './config/dao_fork_accounts_config.json' @@ -66,7 +69,7 @@ export async function runBlock(this: VM, opts: RunBlockOpts): Promise { const castedTx = opts.tx for (const accessListItem of castedTx.AccessListJSON) { - const address = toBuffer(accessListItem.address) + const address = toBytes(accessListItem.address) state.addWarmedAddress(address) for (const storageKey of accessListItem.storageKeys) { - state.addWarmedStorage(address, toBuffer(storageKey)) + state.addWarmedStorage(address, toBytes(storageKey)) } } } @@ -209,7 +210,7 @@ async function _runTx(this: VM, opts: RunTxOpts): Promise { if (this.DEBUG) { debug( `New tx run hash=${ - opts.tx.isSigned() ? opts.tx.hash().toString('hex') : 'unsigned' + opts.tx.isSigned() ? bytesToHex(opts.tx.hash()) : 'unsigned' } sender=${caller}` ) } @@ -218,15 +219,15 @@ async function _runTx(this: VM, opts: RunTxOpts): Promise { // Add origin and precompiles to warm addresses const activePrecompiles = this.evm.precompiles for (const [addressStr] of activePrecompiles.entries()) { - state.addWarmedAddress(Buffer.from(addressStr, 'hex')) + state.addWarmedAddress(hexToBytes(addressStr)) } - state.addWarmedAddress(caller.buf) + state.addWarmedAddress(caller.bytes) if (tx.to) { // Note: in case we create a contract, we do this in EVMs `_executeCreate` (this is also correct in inner calls, per the EIP) - state.addWarmedAddress(tx.to.buf) + state.addWarmedAddress(tx.to.bytes) } if (this._common.isActivatedEIP(3651) === true) { - state.addWarmedAddress(block.header.coinbase.buf) + state.addWarmedAddress(block.header.coinbase.bytes) } } @@ -264,7 +265,10 @@ async function _runTx(this: VM, opts: RunTxOpts): Promise { const { nonce, balance } = fromAccount debug(`Sender's pre-tx balance is ${balance}`) // EIP-3607: Reject transactions from senders with deployed code - if (this._common.isActivatedEIP(3607) === true && !fromAccount.codeHash.equals(KECCAK256_NULL)) { + if ( + this._common.isActivatedEIP(3607) === true && + !equalsBytes(fromAccount.codeHash, KECCAK256_NULL) + ) { const msg = _errorMsg('invalid sender address, address is not EOA (EIP-3607)', this, block, tx) throw new Error(msg) } @@ -411,7 +415,7 @@ async function _runTx(this: VM, opts: RunTxOpts): Promise { if (this.DEBUG) { debug( `Running tx=0x${ - tx.isSigned() ? tx.hash().toString('hex') : 'unsigned' + tx.isSigned() ? bytesToHex(tx.hash()) : 'unsigned' } with caller=${caller} gasLimit=${gasLimit} to=${ to?.toString() ?? 'none' } value=${value} data=0x${short(data)}` @@ -438,7 +442,7 @@ async function _runTx(this: VM, opts: RunTxOpts): Promise { debug('-'.repeat(100)) debug( `Received tx execResult: [ executionGasUsed=${executionGasUsed} exceptionError=${ - exceptionError ? `'${exceptionError.error}'` : 'none' + exceptionError !== undefined ? `'${exceptionError.error}'` : 'none' } returnValue=0x${short(returnValue)} gasRefund=${results.gasRefund ?? 0} ]` ) } @@ -515,10 +519,10 @@ async function _runTx(this: VM, opts: RunTxOpts): Promise { /* * Cleanup accounts */ - if (results.execResult.selfdestruct) { + if (results.execResult.selfdestruct !== undefined) { const keys = Object.keys(results.execResult.selfdestruct) for (const k of keys) { - const address = new Address(Buffer.from(k, 'hex')) + const address = new Address(hexToBytes(k)) await state.deleteAccount(address) if (this.DEBUG) { debug(`tx selfdestruct on address=${address}`) @@ -546,7 +550,7 @@ async function _runTx(this: VM, opts: RunTxOpts): Promise { if (this.DEBUG) { debug( `tx run finished hash=${ - opts.tx.isSigned() ? opts.tx.hash().toString('hex') : 'unsigned' + opts.tx.isSigned() ? bytesToPrefixedHexString(opts.tx.hash()) : 'unsigned' } sender=${caller}` ) } @@ -610,7 +614,7 @@ export async function generateTxReceipt( if (this._common.gteHardfork(Hardfork.Byzantium) === true) { // Post-Byzantium receipt = { - status: txResult.execResult.exceptionError ? 0 : 1, // Receipts have a 0 as status on error + status: txResult.execResult.exceptionError !== undefined ? 0 : 1, // Receipts have a 0 as status on error ...baseReceipt, } as PostByzantiumTxReceipt } else { @@ -624,7 +628,7 @@ export async function generateTxReceipt( } else { // Typed EIP-2718 Transaction receipt = { - status: txResult.execResult.exceptionError ? 0 : 1, + status: txResult.execResult.exceptionError !== undefined ? 0 : 1, ...baseReceipt, } as PostByzantiumTxReceipt } diff --git a/packages/vm/src/types.ts b/packages/vm/src/types.ts index 4af717c055..727f2be983 100644 --- a/packages/vm/src/types.ts +++ b/packages/vm/src/types.ts @@ -19,7 +19,7 @@ export interface BaseTxReceipt { /** * Bloom bitvector */ - bitvector: Buffer + bitvector: Uint8Array /** * Logs emitted */ @@ -34,7 +34,7 @@ export interface PreByzantiumTxReceipt extends BaseTxReceipt { /** * Intermediary state root */ - stateRoot: Buffer + stateRoot: Uint8Array } /** @@ -187,13 +187,13 @@ export interface SealBlockOpts { * For PoW, the nonce. * Overrides the value passed in the constructor. */ - nonce?: Buffer + nonce?: Uint8Array /** * For PoW, the mixHash. * Overrides the value passed in the constructor. */ - mixHash?: Buffer + mixHash?: Uint8Array } /** @@ -207,7 +207,7 @@ export interface RunBlockOpts { /** * Root of the state trie */ - root?: Buffer + root?: Uint8Array /** * Whether to generate the stateRoot and other related fields. * If `true`, `runBlock` will set the fields `stateRoot`, `receiptTrie`, `gasUsed`, and `bloom` (logs bloom) after running the block. @@ -263,7 +263,7 @@ export interface RunBlockResult { /** * The stateRoot after executing the block */ - stateRoot: Buffer + stateRoot: Uint8Array /** * The gas used after executing the block */ @@ -271,11 +271,11 @@ export interface RunBlockResult { /** * The bloom filter of the LOGs (events) after executing the block */ - logsBloom: Buffer + logsBloom: Uint8Array /** * The receipt root after executing the block */ - receiptsRoot: Buffer + receiptsRoot: Uint8Array } export interface AfterBlockEvent extends RunBlockResult { diff --git a/packages/vm/src/vm.ts b/packages/vm/src/vm.ts index 5d7793abfd..678e5b4ee8 100644 --- a/packages/vm/src/vm.ts +++ b/packages/vm/src/vm.ts @@ -3,6 +3,7 @@ import { Chain, Common } from '@ethereumjs/common' import { EVM, getActivePrecompiles } from '@ethereumjs/evm' import { DefaultStateManager } from '@ethereumjs/statemanager' import { Account, Address, AsyncEventEmitter, TypeOutput, toType } from '@ethereumjs/util' +import { hexToBytes } from 'ethereum-cryptography/utils' import { promisify } from 'util' import { buildBlock } from './buildBlock' @@ -113,13 +114,13 @@ export class VM { this.blockchain = opts.blockchain ?? new (Blockchain as any)({ common: this._common }) // TODO tests - if (opts.eei) { - if (opts.evm) { + if (opts.eei !== undefined) { + if (opts.evm !== undefined) { throw new Error('cannot specify EEI if EVM opt provided') } this.eei = opts.eei } else { - if (opts.evm) { + if (opts.evm !== undefined) { this.eei = opts.evm.eei } else { this.eei = new EEI(this.stateManager, this._common, this.blockchain) @@ -127,7 +128,7 @@ export class VM { } // TODO tests - if (opts.evm) { + if (opts.evm !== undefined) { this.evm = opts.evm } else { this.evm = new EVM({ @@ -177,11 +178,11 @@ export class VM { await this.eei.checkpoint() // put 1 wei in each of the precompiles in order to make the accounts non-empty and thus not have them deduct `callNewAccount` gas. for (const [addressStr] of getActivePrecompiles(this._common)) { - const address = new Address(Buffer.from(addressStr, 'hex')) + const address = new Address(hexToBytes(addressStr)) const account = await this.eei.getAccount(address) // Only do this if it is not overridden in genesis // Note: in the case that custom genesis has storage fields, this is preserved - if (account.isEmpty()) { + if (account.isEmpty() === true) { const newAccount = Account.fromAccountData({ balance: 1, storageRoot: account.storageRoot, diff --git a/packages/vm/test/api/EIPs/eip-1153.spec.ts b/packages/vm/test/api/EIPs/eip-1153.spec.ts index dabcb8cb88..25bb2dd60a 100644 --- a/packages/vm/test/api/EIPs/eip-1153.spec.ts +++ b/packages/vm/test/api/EIPs/eip-1153.spec.ts @@ -1,6 +1,7 @@ import { Chain, Common, Hardfork } from '@ethereumjs/common' import { Transaction } from '@ethereumjs/tx' -import { Account, Address, bufferToInt, privateToAddress } from '@ethereumjs/util' +import { Account, Address, bytesToInt, privateToAddress } from '@ethereumjs/util' +import { hexToBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' import { VM } from '../../../src/vm' @@ -11,10 +12,7 @@ interface Test { transactions: Transaction[] } -const senderKey = Buffer.from( - 'e331b6d69882b4cb4ea581d88e0b604039a3de5967688d3dcffdd2270c0fd109', - 'hex' -) +const senderKey = hexToBytes('e331b6d69882b4cb4ea581d88e0b604039a3de5967688d3dcffdd2270c0fd109') tape('EIP 1153: transient storage', (t) => { const initialGas = BigInt(0xffffffffff) @@ -54,7 +52,7 @@ tape('EIP 1153: transient storage', (t) => { }) for (const { code, address } of test.contracts) { - await vm.stateManager.putContractCode(address, Buffer.from(code, 'hex')) + await vm.stateManager.putContractCode(address, hexToBytes(code)) } const fromAddress = new Address(privateToAddress(senderKey)) @@ -70,10 +68,10 @@ tape('EIP 1153: transient storage', (t) => { t.test('should tload and tstore', async (st) => { const code = '60026001b46001b360005260206000F3' - const returndata = Buffer.alloc(32) + const returndata = new Uint8Array(32) returndata[31] = 0x02 - const address = new Address(Buffer.from('000000000000000000000000636F6E7472616374', 'hex')) + const address = new Address(hexToBytes('000000000000000000000000636F6E7472616374')) const tx = Transaction.fromTxData({ gasLimit: BigInt(21000 + 9000), to: address, @@ -112,7 +110,7 @@ tape('EIP 1153: transient storage', (t) => { // is 0, then the transient storage is cleared between // transactions const code = '36600014630000001c5760016300000012575b60ff6000b4600080f35b6000b360005260206000f3' - const address = new Address(Buffer.from('000000000000000000000000636F6E7472616374', 'hex')) + const address = new Address(hexToBytes('000000000000000000000000636F6E7472616374')) const test = { contracts: [{ address, code }], @@ -120,7 +118,7 @@ tape('EIP 1153: transient storage', (t) => { Transaction.fromTxData({ gasLimit: BigInt(15000000), to: address, - data: Buffer.alloc(32), + data: new Uint8Array(32), }).sign(senderKey), Transaction.fromTxData({ nonce: 1, @@ -164,15 +162,15 @@ tape('EIP 1153: transient storage', (t) => { const [result1, result2] = await runTest(test, st) st.equal(result1.execResult.exceptionError, undefined) - st.equal(bufferToInt(result2.execResult.returnValue), 0) + st.equal(bytesToInt(result2.execResult.returnValue), 0) st.end() }) t.test('tload should not keep reverted changes', async (st) => { // logic address has a contract with transient storage logic in it - const logicAddress = new Address(Buffer.from('EA674fdDe714fd979de3EdF0F56AA9716B898ec8', 'hex')) + const logicAddress = new Address(hexToBytes('EA674fdDe714fd979de3EdF0F56AA9716B898ec8')) // calling address is the address that calls the logic address - const callingAddress = new Address(Buffer.alloc(20, 0xff)) + const callingAddress = new Address(new Uint8Array(20).fill(0xff)) // Perform 3 calls: // - TSTORE, return @@ -659,7 +657,7 @@ tape('EIP 1153: transient storage', (t) => { } const [result] = await runTest(test, st) - st.equal(bufferToInt(result.execResult.returnValue), 0xaa) + st.equal(bytesToInt(result.execResult.returnValue), 0xaa) st.end() }) }) diff --git a/packages/vm/test/api/EIPs/eip-1283-net-gas-metering.spec.ts b/packages/vm/test/api/EIPs/eip-1283-net-gas-metering.spec.ts index 47d9d16fb0..e23656a4ed 100644 --- a/packages/vm/test/api/EIPs/eip-1283-net-gas-metering.spec.ts +++ b/packages/vm/test/api/EIPs/eip-1283-net-gas-metering.spec.ts @@ -1,5 +1,6 @@ import { Chain, Common, Hardfork } from '@ethereumjs/common' -import { Address, bigIntToBuffer, setLengthLeft } from '@ethereumjs/util' +import { Address, bigIntToBytes, setLengthLeft } from '@ethereumjs/util' +import { hexToBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' import { VM } from '../../../src/vm' @@ -31,18 +32,18 @@ const testCases = [ tape('Constantinople: EIP-1283', async (t) => { t.test('net-metering SSTORE', async (st) => { - const caller = new Address(Buffer.from('0000000000000000000000000000000000000000', 'hex')) - const addr = new Address(Buffer.from('00000000000000000000000000000000000000ff', 'hex')) - const key = setLengthLeft(bigIntToBuffer(BigInt(0)), 32) + const caller = new Address(hexToBytes('0000000000000000000000000000000000000000')) + const addr = new Address(hexToBytes('00000000000000000000000000000000000000ff')) + const key = setLengthLeft(bigIntToBytes(BigInt(0)), 32) for (const testCase of testCases) { const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Constantinople }) const vm = await VM.create({ common }) const account = createAccount(BigInt(0), BigInt(0)) await vm.stateManager.putAccount(addr, account) - await vm.stateManager.putContractCode(addr, Buffer.from(testCase.code, 'hex')) + await vm.stateManager.putContractCode(addr, hexToBytes(testCase.code)) if (testCase.original !== BigInt(0)) { - await vm.stateManager.putContractStorage(addr, key, bigIntToBuffer(testCase.original)) + await vm.stateManager.putContractStorage(addr, key, bigIntToBytes(testCase.original)) } const runCallArgs = { diff --git a/packages/vm/test/api/EIPs/eip-1559-FeeMarket.spec.ts b/packages/vm/test/api/EIPs/eip-1559-FeeMarket.spec.ts index e9d6383d28..71e513012f 100644 --- a/packages/vm/test/api/EIPs/eip-1559-FeeMarket.spec.ts +++ b/packages/vm/test/api/EIPs/eip-1559-FeeMarket.spec.ts @@ -5,7 +5,8 @@ import { FeeMarketEIP1559Transaction, Transaction, } from '@ethereumjs/tx' -import { Address, bigIntToBuffer, privateToAddress, setLengthLeft } from '@ethereumjs/util' +import { Address, bigIntToBytes, privateToAddress, setLengthLeft } from '@ethereumjs/util' +import { hexToBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' import { VM } from '../../../src/vm' @@ -32,8 +33,8 @@ common.hardforkBlock = function (hardfork: string | undefined) { return BigInt(0) } -const coinbase = new Address(Buffer.from('11'.repeat(20), 'hex')) -const pkey = Buffer.from('20'.repeat(32), 'hex') +const coinbase = new Address(hexToBytes('11'.repeat(20))) +const pkey = hexToBytes('20'.repeat(32)) const sender = new Address(privateToAddress(pkey)) /** @@ -162,7 +163,7 @@ tape('EIP1559 tests', (t) => { }) t.test('gasPrice uses the effective gas price', async (st) => { - const contractAddress = new Address(Buffer.from('20'.repeat(20), 'hex')) + const contractAddress = new Address(hexToBytes('20'.repeat(20))) const tx = new FeeMarketEIP1559Transaction( { maxFeePerGas: GWEI * BigInt(5), @@ -189,16 +190,16 @@ tape('EIP1559 tests', (t) => { */ // (This code returns the reported GASPRICE) - const code = Buffer.from('3A60005260206000F3', 'hex') + const code = hexToBytes('3A60005260206000F3') await vm.stateManager.putContractCode(contractAddress, code) const result = await vm.runTx({ tx: block.transactions[0], block }) const returnValue = result.execResult.returnValue const expectedCost = GWEI * BigInt(3) - const expectedReturn = setLengthLeft(bigIntToBuffer(expectedCost), 32) + const expectedReturn = setLengthLeft(bigIntToBytes(expectedCost), 32) - st.ok(returnValue.equals(expectedReturn)) + st.deepEquals(returnValue, expectedReturn) st.end() }) }) diff --git a/packages/vm/test/api/EIPs/eip-2315.spec.ts b/packages/vm/test/api/EIPs/eip-2315.spec.ts index b9fbfc7286..2585682aaf 100644 --- a/packages/vm/test/api/EIPs/eip-2315.spec.ts +++ b/packages/vm/test/api/EIPs/eip-2315.spec.ts @@ -1,4 +1,5 @@ import { Chain, Common, Hardfork } from '@ethereumjs/common' +import { hexToBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' import { VM } from '../../../src/vm' @@ -18,7 +19,7 @@ tape('Berlin: EIP 2315 tests', (t) => { }) const result = await vm.evm.runCode!({ - code: Buffer.from(test.code, 'hex'), + code: hexToBytes(test.code), gasLimit: BigInt(0xffffffffff), }) diff --git a/packages/vm/test/api/EIPs/eip-2565-modexp-gas-cost.spec.ts b/packages/vm/test/api/EIPs/eip-2565-modexp-gas-cost.spec.ts index 371427058c..303ed7879d 100644 --- a/packages/vm/test/api/EIPs/eip-2565-modexp-gas-cost.spec.ts +++ b/packages/vm/test/api/EIPs/eip-2565-modexp-gas-cost.spec.ts @@ -1,5 +1,6 @@ import { Chain, Common, Hardfork } from '@ethereumjs/common' import { Address } from '@ethereumjs/util' +import { bytesToHex, equalsBytes, hexToBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' import { VM } from '../../../src/vm' @@ -14,13 +15,13 @@ tape('EIP-2565 ModExp gas cost tests', (t) => { for (const test of testData) { const testName = test.Name - const to = new Address(Buffer.from('0000000000000000000000000000000000000005', 'hex')) + const to = new Address(hexToBytes('0000000000000000000000000000000000000005')) const result = await vm.evm.runCall({ caller: Address.zero(), gasLimit: BigInt(0xffffffffff), to, value: BigInt(0), - data: Buffer.from(test.Input, 'hex'), + data: hexToBytes(test.Input), }) if (result.execResult.executionGasUsed !== BigInt(test.Gas)) { @@ -30,16 +31,16 @@ tape('EIP-2565 ModExp gas cost tests', (t) => { continue } - if (result.execResult.exceptionError) { + if (result.execResult.exceptionError !== undefined) { st.fail(`[${testName}]: Call should not fail`) continue } - if (!result.execResult.returnValue.equals(Buffer.from(test.Expected, 'hex'))) { + if (!equalsBytes(result.execResult.returnValue, hexToBytes(test.Expected))) { st.fail( `[${testName}]: Return value not the expected value (expected: ${ test.Expected - }, received: ${result.execResult.returnValue.toString('hex')})` + }, received: ${bytesToHex(result.execResult.returnValue)})` ) continue } diff --git a/packages/vm/test/api/EIPs/eip-2929.spec.ts b/packages/vm/test/api/EIPs/eip-2929.spec.ts index 4ff50d3181..a446949f66 100644 --- a/packages/vm/test/api/EIPs/eip-2929.spec.ts +++ b/packages/vm/test/api/EIPs/eip-2929.spec.ts @@ -1,6 +1,7 @@ import { Chain, Common, Hardfork } from '@ethereumjs/common' import { Transaction } from '@ethereumjs/tx' import { Account, Address } from '@ethereumjs/util' +import { hexToBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' import { VM } from '../../../src/vm' @@ -8,11 +9,8 @@ import { VM } from '../../../src/vm' // Test cases source: https://gist.github.com/holiman/174548cad102096858583c6fbbb0649a tape('EIP 2929: gas cost tests', (t) => { const initialGas = BigInt(0xffffffffff) - const address = new Address(Buffer.from('000000000000000000000000636F6E7472616374', 'hex')) - const senderKey = Buffer.from( - 'e331b6d69882b4cb4ea581d88e0b604039a3de5967688d3dcffdd2270c0fd109', - 'hex' - ) + const address = new Address(hexToBytes('000000000000000000000000636F6E7472616374')) + const senderKey = hexToBytes('e331b6d69882b4cb4ea581d88e0b604039a3de5967688d3dcffdd2270c0fd109') const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Berlin, eips: [2929] }) const runTest = async function (test: any, st: tape.Test) { @@ -48,7 +46,7 @@ tape('EIP 2929: gas cost tests', (t) => { i++ }) - await vm.stateManager.putContractCode(address, Buffer.from(test.code, 'hex')) + await vm.stateManager.putContractCode(address, hexToBytes(test.code)) const unsignedTx = Transaction.fromTxData({ gasLimit: initialGas, // ensure we pass a lot of gas, so we do not run out of gas @@ -66,18 +64,15 @@ tape('EIP 2929: gas cost tests', (t) => { const runCodeTest = async function (code: string, expectedGasUsed: bigint, st: tape.Test) { // setup the accounts for this test - const privateKey = Buffer.from( - 'e331b6d69882b4cb4ea581d88e0b604039a3de5967688d3dcffdd2270c0fd109', - 'hex' - ) - const contractAddress = new Address( - Buffer.from('00000000000000000000000000000000000000ff', 'hex') + const privateKey = hexToBytes( + 'e331b6d69882b4cb4ea581d88e0b604039a3de5967688d3dcffdd2270c0fd109' ) + const contractAddress = new Address(hexToBytes('00000000000000000000000000000000000000ff')) const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Berlin, eips: [2929] }) const vm = await VM.create({ common }) - await vm.stateManager.putContractCode(contractAddress, Buffer.from(code, 'hex')) // setup the contract code + await vm.stateManager.putContractCode(contractAddress, hexToBytes(code)) // setup the contract code // setup the call arguments const unsignedTx = Transaction.fromTxData({ diff --git a/packages/vm/test/api/EIPs/eip-2930-accesslists.spec.ts b/packages/vm/test/api/EIPs/eip-2930-accesslists.spec.ts index 4a28cb1f92..59af2f9f5e 100644 --- a/packages/vm/test/api/EIPs/eip-2930-accesslists.spec.ts +++ b/packages/vm/test/api/EIPs/eip-2930-accesslists.spec.ts @@ -1,6 +1,7 @@ import { Chain, Common, Hardfork } from '@ethereumjs/common' import { AccessListEIP2930Transaction } from '@ethereumjs/tx' -import { Account, Address, bufferToHex } from '@ethereumjs/util' +import { Account, Address, bytesToHex } from '@ethereumjs/util' +import { hexToBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' import { VM } from '../../../src/vm' @@ -11,22 +12,19 @@ const common = new Common({ hardfork: Hardfork.Berlin, }) -const validAddress = Buffer.from('00000000000000000000000000000000000000ff', 'hex') -const validSlot = Buffer.from('00'.repeat(32), 'hex') +const validAddress = hexToBytes('00000000000000000000000000000000000000ff') +const validSlot = hexToBytes('00'.repeat(32)) // setup the accounts for this test -const privateKey = Buffer.from( - 'e331b6d69882b4cb4ea581d88e0b604039a3de5967688d3dcffdd2270c0fd109', - 'hex' -) +const privateKey = hexToBytes('e331b6d69882b4cb4ea581d88e0b604039a3de5967688d3dcffdd2270c0fd109') const contractAddress = new Address(validAddress) tape('EIP-2930 Optional Access Lists tests', (t) => { t.test('VM should charge the right gas when using access list transactions', async (st) => { const access = [ { - address: bufferToHex(validAddress), - storageKeys: [bufferToHex(validSlot)], + address: bytesToHex(validAddress), + storageKeys: [bytesToHex(validSlot)], }, ] const txnWithAccessList = AccessListEIP2930Transaction.fromTxData( @@ -51,7 +49,7 @@ tape('EIP-2930 Optional Access Lists tests', (t) => { const vm = await VM.create({ common }) // contract code PUSH1 0x00 SLOAD STOP - await vm.stateManager.putContractCode(contractAddress, Buffer.from('60005400', 'hex')) + await vm.stateManager.putContractCode(contractAddress, hexToBytes('60005400')) const address = Address.fromPrivateKey(privateKey) const initialBalance = BigInt(10) ** BigInt(18) diff --git a/packages/vm/test/api/EIPs/eip-3074-authcall.spec.ts b/packages/vm/test/api/EIPs/eip-3074-authcall.spec.ts index 9ff636f9b4..33de708963 100644 --- a/packages/vm/test/api/EIPs/eip-3074-authcall.spec.ts +++ b/packages/vm/test/api/EIPs/eip-3074-authcall.spec.ts @@ -4,15 +4,17 @@ import { ERROR } from '@ethereumjs/evm/dist/exceptions' import { Transaction } from '@ethereumjs/tx' import { Address, - bigIntToBuffer, - bufferToBigInt, + bigIntToBytes, + bytesToBigInt, + concatBytesNoTypeCheck, ecsign, privateToAddress, setLengthLeft, - toBuffer, + toBytes, zeros, } from '@ethereumjs/util' import { keccak256 } from 'ethereum-cryptography/keccak' +import { hexToBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' import { VM } from '../../../src/vm' @@ -27,10 +29,7 @@ const common = new Common({ }) // setup the accounts for this test -const privateKey = Buffer.from( - 'e331b6d69882b4cb4ea581d88e0b604039a3de5967688d3dcffdd2270c0fd109', - 'hex' -) +const privateKey = hexToBytes('e331b6d69882b4cb4ea581d88e0b604039a3de5967688d3dcffdd2270c0fd109') const authAddress = new Address(privateToAddress(privateKey)) const block = Block.fromBlockData( @@ -42,21 +41,21 @@ const block = Block.fromBlockData( { common } ) -const callerPrivateKey = Buffer.from('44'.repeat(32), 'hex') +const callerPrivateKey = hexToBytes('44'.repeat(32)) const callerAddress = new Address(privateToAddress(callerPrivateKey)) const PREBALANCE = BigInt(10000000) const address = new Address(privateToAddress(privateKey)) -const contractAddress = new Address(Buffer.from('ff'.repeat(20), 'hex')) -const contractStorageAddress = new Address(Buffer.from('ee'.repeat(20), 'hex')) +const contractAddress = new Address(hexToBytes('ff'.repeat(20))) +const contractStorageAddress = new Address(hexToBytes('ee'.repeat(20))) // Bytecode to exit call frame and return the topmost stack item -const RETURNTOP = Buffer.from('60005260206000F3', 'hex') +const RETURNTOP = hexToBytes('60005260206000F3') //Bytecode to exit call frame and return the current memory size -const RETURNMEMSIZE = Buffer.from('5960005260206000F3', 'hex') +const RETURNMEMSIZE = hexToBytes('5960005260206000F3') // Bytecode to store CALLER in slot 0 and GAS in slot 1 and the first 32 bytes of the input in slot 2 // Returns the entire input as output -const STORECALLER = Buffer.from('5A60015533600055600035600255366000600037366000F3', 'hex') +const STORECALLER = hexToBytes('5A60015533600055600035600255366000600037366000F3') /** * This signs a message to be used for AUTH opcodes @@ -65,12 +64,12 @@ const STORECALLER = Buffer.from('5A60015533600055600035600255366000600037366000F * @param privateKey - The private key of the account to sign * @returns The signed message */ -function signMessage(commitUnpadded: Buffer, address: Address, privateKey: Buffer) { +function signMessage(commitUnpadded: Uint8Array, address: Address, privateKey: Uint8Array) { const commit = setLengthLeft(commitUnpadded, 32) - const paddedInvokerAddress = setLengthLeft(address.buf, 32) - const chainId = setLengthLeft(bigIntToBuffer(common.chainId()), 32) - const message = Buffer.concat([Buffer.from('03', 'hex'), chainId, paddedInvokerAddress, commit]) - const msgHash = Buffer.from(keccak256(message)) + const paddedInvokerAddress = setLengthLeft(address.bytes, 32) + const chainId = setLengthLeft(bigIntToBytes(common.chainId()), 32) + const message = concatBytesNoTypeCheck(hexToBytes('03'), chainId, paddedInvokerAddress, commit) + const msgHash = keccak256(message) return ecsign(msgHash, privateKey) } @@ -79,34 +78,34 @@ function signMessage(commitUnpadded: Buffer, address: Address, privateKey: Buffe * @param commitUnpadded - The commit * @param signature - The signature as obtained by `signMessage` * @param address - The address which signed the commit - * @param msizeBuffer - Optional: memory size buffer, defaults to `0x80` (128 bytes) + * @param msizeBytes - Optional: memory size buffUint8Arrayer, defaults to `0x80` (128 bytes) */ function getAuthCode( - commitUnpadded: Buffer, + commitUnpadded: Uint8Array, signature: ECDSASignature, address: Address, - msizeBuffer?: Buffer + msizeBuffer?: Uint8Array ) { const commit = setLengthLeft(commitUnpadded, 32) - let v: Buffer + let v: Uint8Array if (signature.v === BigInt(27)) { - v = setLengthLeft(Buffer.from('00', 'hex'), 32) + v = setLengthLeft(hexToBytes('00'), 32) } else if (signature.v === BigInt(28)) { - v = setLengthLeft(Buffer.from('01', 'hex'), 32) + v = setLengthLeft(hexToBytes('01'), 32) } else { - v = setLengthLeft(toBuffer(signature.v), 32) + v = setLengthLeft(toBytes(signature.v), 32) } - const PUSH32 = Buffer.from('7F', 'hex') - const AUTH = Buffer.from('F6', 'hex') - const MSTORE = Buffer.from('52', 'hex') + const PUSH32 = hexToBytes('7F') + const AUTH = hexToBytes('F6') + const MSTORE = hexToBytes('52') const mslot0 = zeros(32) - const mslot1 = Buffer.concat([zeros(31), Buffer.from('20', 'hex')]) - const mslot2 = Buffer.concat([zeros(31), Buffer.from('40', 'hex')]) - const mslot3 = Buffer.concat([zeros(31), Buffer.from('60', 'hex')]) - const addressBuffer = setLengthLeft(address.buf, 32) + const mslot1 = concatBytesNoTypeCheck(zeros(31), hexToBytes('20')) + const mslot2 = concatBytesNoTypeCheck(zeros(31), hexToBytes('40')) + const mslot3 = concatBytesNoTypeCheck(zeros(31), hexToBytes('60')) + const addressBuffer = setLengthLeft(address.bytes, 32) // This bytecode setups the stack to be used for AUTH - return Buffer.concat([ + return concatBytesNoTypeCheck( PUSH32, signature.s, PUSH32, @@ -127,13 +126,13 @@ function getAuthCode( PUSH32, mslot3, MSTORE, - Buffer.from('60', 'hex'), - msizeBuffer ?? Buffer.from('80', 'hex'), - Buffer.from('6000', 'hex'), + hexToBytes('60'), + msizeBuffer ?? hexToBytes('80'), + hexToBytes('6000'), PUSH32, addressBuffer, - AUTH, - ]) + AUTH + ) } // This type has all arguments to be used on AUTHCALL @@ -153,14 +152,14 @@ type AuthcallData = { * @param position * @param value */ -function MSTORE(position: Buffer, value: Buffer) { - return Buffer.concat([ - Buffer.from('7F', 'hex'), +function MSTORE(position: Uint8Array, value: Uint8Array) { + return concatBytesNoTypeCheck( + hexToBytes('7F'), setLengthLeft(value, 32), - Buffer.from('7F', 'hex'), + hexToBytes('7F'), setLengthLeft(position, 32), - Buffer.from('52', 'hex'), - ]) + hexToBytes('52') + ) } /** @@ -169,16 +168,16 @@ function MSTORE(position: Buffer, value: Buffer) { * @returns - The bytecode to execute AUTHCALL */ function getAuthCallCode(data: AuthcallData) { - const gasLimitBuffer = setLengthLeft(bigIntToBuffer(data.gasLimit ?? BigInt(0)), 32) - const addressBuffer = setLengthLeft(data.address.buf, 32) - const valueBuffer = setLengthLeft(bigIntToBuffer(data.value ?? BigInt(0)), 32) - const valueExtBuffer = setLengthLeft(bigIntToBuffer(data.valueExt ?? BigInt(0)), 32) - const argsOffsetBuffer = setLengthLeft(bigIntToBuffer(data.argsOffset ?? BigInt(0)), 32) - const argsLengthBuffer = setLengthLeft(bigIntToBuffer(data.argsLength ?? BigInt(0)), 32) - const retOffsetBuffer = setLengthLeft(bigIntToBuffer(data.retOffset ?? BigInt(0)), 32) - const retLengthBuffer = setLengthLeft(bigIntToBuffer(data.retLength ?? BigInt(0)), 32) - const PUSH32 = Buffer.from('7f', 'hex') - const AUTHCALL = Buffer.from('f7', 'hex') + const gasLimitBuffer = setLengthLeft(bigIntToBytes(data.gasLimit ?? BigInt(0)), 32) + const addressBuffer = setLengthLeft(data.address.bytes, 32) + const valueBuffer = setLengthLeft(bigIntToBytes(data.value ?? BigInt(0)), 32) + const valueExtBuffer = setLengthLeft(bigIntToBytes(data.valueExt ?? BigInt(0)), 32) + const argsOffsetBuffer = setLengthLeft(bigIntToBytes(data.argsOffset ?? BigInt(0)), 32) + const argsLengthBuffer = setLengthLeft(bigIntToBytes(data.argsLength ?? BigInt(0)), 32) + const retOffsetBuffer = setLengthLeft(bigIntToBytes(data.retOffset ?? BigInt(0)), 32) + const retLengthBuffer = setLengthLeft(bigIntToBytes(data.retLength ?? BigInt(0)), 32) + const PUSH32 = hexToBytes('7f') + const AUTHCALL = hexToBytes('f7') const order = [ retLengthBuffer, retOffsetBuffer, @@ -190,18 +189,18 @@ function getAuthCallCode(data: AuthcallData) { gasLimitBuffer, ] const bufferList = [] - order.map((e: Buffer) => { + order.map((e: Uint8Array) => { bufferList.push(PUSH32) bufferList.push(e) }) bufferList.push(AUTHCALL) - return Buffer.concat(bufferList) + return concatBytesNoTypeCheck(...bufferList) } // This flips the signature: the result is a signature which has the same public key upon key recovery, // But the s-value is now > N_DIV_2 function flipSignature(signature: any) { - const s = bufferToBigInt(signature.s) + const s = bytesToBigInt(signature.s) const flipped = 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141n - s if (signature.v === 27) { @@ -209,16 +208,16 @@ function flipSignature(signature: any) { } else { signature.v = 27 } - signature.s = setLengthLeft(bigIntToBuffer(flipped), 32) + signature.s = setLengthLeft(bigIntToBytes(flipped), 32) return signature } tape('EIP-3074 AUTH', (t) => { t.test('Should execute AUTH correctly', async (st) => { const vm = await VM.create({ common }) - const message = Buffer.from('01', 'hex') + const message = hexToBytes('01') const signature = signMessage(message, contractAddress, privateKey) - const code = Buffer.concat([getAuthCode(message, signature, authAddress), RETURNTOP]) + const code = concatBytesNoTypeCheck(getAuthCode(message, signature, authAddress), RETURNTOP) await vm.stateManager.putContractCode(contractAddress, code) const tx = Transaction.fromTxData({ @@ -233,15 +232,15 @@ tape('EIP-3074 AUTH', (t) => { const result = await vm.runTx({ tx, block, skipHardForkValidation: true }) const buf = result.execResult.returnValue.slice(31) - st.ok(buf.equals(Buffer.from('01', 'hex')), 'auth should return 1') + st.deepEquals(buf, hexToBytes('01'), 'auth should return 1') }) t.test('Should not set AUTH if signature is invalid', async (st) => { const vm = await VM.create({ common }) - const message = Buffer.from('01', 'hex') + const message = hexToBytes('01') const signature = signMessage(message, contractAddress, privateKey) signature.r = signature.s - const code = Buffer.concat([getAuthCode(message, signature, authAddress), RETURNTOP]) + const code = concatBytesNoTypeCheck(getAuthCode(message, signature, authAddress), RETURNTOP) await vm.stateManager.putContractCode(contractAddress, code) const tx = Transaction.fromTxData({ @@ -256,16 +255,16 @@ tape('EIP-3074 AUTH', (t) => { const result = await vm.runTx({ tx, block, skipHardForkValidation: true }) const buf = result.execResult.returnValue - st.ok(buf.equals(zeros(32)), 'auth puts 0 on stack on invalid signature') + st.deepEquals(buf, zeros(32), 'auth puts 0 on stack on invalid signature') }) t.test('Should not set AUTH if reported address is invalid', async (st) => { const vm = await VM.create({ common }) - const message = Buffer.from('01', 'hex') + const message = hexToBytes('01') const signature = signMessage(message, contractAddress, privateKey) signature.r = signature.s // use the contractAddress instead of authAddress for the expected address (this should fail) - const code = Buffer.concat([getAuthCode(message, signature, contractAddress), RETURNTOP]) + const code = concatBytesNoTypeCheck(getAuthCode(message, signature, contractAddress), RETURNTOP) await vm.stateManager.putContractCode(contractAddress, code) const tx = Transaction.fromTxData({ @@ -280,14 +279,14 @@ tape('EIP-3074 AUTH', (t) => { const result = await vm.runTx({ tx, block, skipHardForkValidation: true }) const buf = result.execResult.returnValue - st.ok(buf.equals(zeros(32)), 'auth puts 0') + st.deepEquals(buf, zeros(32), 'auth puts 0') }) t.test('Should throw if signature s > N_DIV_2', async (st) => { const vm = await VM.create({ common }) - const message = Buffer.from('01', 'hex') + const message = hexToBytes('01') const signature = flipSignature(signMessage(message, contractAddress, privateKey)) - const code = Buffer.concat([getAuthCode(message, signature, authAddress), RETURNTOP]) + const code = concatBytesNoTypeCheck(getAuthCode(message, signature, authAddress), RETURNTOP) await vm.stateManager.putContractCode(contractAddress, code) const tx = Transaction.fromTxData({ @@ -306,14 +305,14 @@ tape('EIP-3074 AUTH', (t) => { t.test('Should be able to call AUTH multiple times', async (st) => { const vm = await VM.create({ common }) - const message = Buffer.from('01', 'hex') + const message = hexToBytes('01') const signature = signMessage(message, contractAddress, privateKey) const signature2 = signMessage(message, contractAddress, callerPrivateKey) - const code = Buffer.concat([ + const code = concatBytesNoTypeCheck( getAuthCode(message, signature, authAddress), getAuthCode(message, signature2, callerAddress), - RETURNTOP, - ]) + RETURNTOP + ) await vm.stateManager.putContractCode(contractAddress, code) const tx = Transaction.fromTxData({ @@ -328,17 +327,17 @@ tape('EIP-3074 AUTH', (t) => { const result = await vm.runTx({ tx, block, skipHardForkValidation: true }) const buf = result.execResult.returnValue.slice(31) - st.ok(buf.equals(Buffer.from('01', 'hex')), 'auth returned right address') + st.deepEquals(buf, hexToBytes('01'), 'auth returned right address') }) t.test('Should use zeros in case that memory size < 128', async (st) => { const vm = await VM.create({ common }) - const message = Buffer.from('00', 'hex') + const message = hexToBytes('00') const signature = signMessage(message, contractAddress, privateKey) - const code = Buffer.concat([ - getAuthCode(message, signature, authAddress, Buffer.from('60', 'hex')), - RETURNTOP, - ]) + const code = concatBytesNoTypeCheck( + getAuthCode(message, signature, authAddress, hexToBytes('60')), + RETURNTOP + ) await vm.stateManager.putContractCode(contractAddress, code) const tx = Transaction.fromTxData({ @@ -353,14 +352,14 @@ tape('EIP-3074 AUTH', (t) => { const result = await vm.runTx({ tx, block, skipHardForkValidation: true }) const buf = result.execResult.returnValue.slice(31) - st.ok(buf.equals(Buffer.from('01', 'hex')), 'auth returned right address') + st.deepEquals(buf, hexToBytes('01'), 'auth returned right address') }) t.test('Should charge memory expansion gas if the memory size > 128', async (st) => { const vm = await VM.create({ common }) - const message = Buffer.from('00', 'hex') + const message = hexToBytes('00') const signature = signMessage(message, contractAddress, privateKey) - const code = Buffer.concat([getAuthCode(message, signature, authAddress), RETURNMEMSIZE]) + const code = concatBytesNoTypeCheck(getAuthCode(message, signature, authAddress), RETURNMEMSIZE) await vm.stateManager.putContractCode(contractAddress, code) const tx = Transaction.fromTxData({ @@ -375,16 +374,17 @@ tape('EIP-3074 AUTH', (t) => { const result = await vm.runTx({ tx, block, skipHardForkValidation: true }) - st.ok( - result.execResult.returnValue.slice(31).equals(Buffer.from('80', 'hex')), + st.deepEquals( + result.execResult.returnValue.slice(31), + hexToBytes('80'), 'reported msize is correct' ) const gas = result.execResult.executionGasUsed - const code2 = Buffer.concat([ - getAuthCode(message, signature, authAddress, Buffer.from('90', 'hex')), - RETURNMEMSIZE, - ]) + const code2 = concatBytesNoTypeCheck( + getAuthCode(message, signature, authAddress, hexToBytes('90')), + RETURNMEMSIZE + ) await vm.stateManager.putContractCode(contractAddress, code2) const tx2 = Transaction.fromTxData({ @@ -398,8 +398,9 @@ tape('EIP-3074 AUTH', (t) => { // the memory size in AUTH is 0x90 (so extra 16 bytes), but memory expands with words (32 bytes) // so the correct amount of msize is 0xa0, not 0x90 - st.ok( - result2.execResult.returnValue.slice(31).equals(Buffer.from('a0', 'hex')), + st.deepEquals( + result2.execResult.returnValue.slice(31), + hexToBytes('a0'), 'reported msize is correct' ) st.ok(result2.execResult.executionGasUsed > gas, 'charged more gas for memory expansion') @@ -408,7 +409,7 @@ tape('EIP-3074 AUTH', (t) => { }) // Setups the environment for the VM, puts `code` at contractAddress and also puts the STORECALLER bytecode at the contractStorageAddress -async function setupVM(code: Buffer) { +async function setupVM(code: Uint8Array) { const vm = await VM.create({ common: common.copy() }) await vm.stateManager.putContractCode(contractAddress, code) await vm.stateManager.putContractCode(contractStorageAddress, STORECALLER) @@ -420,15 +421,15 @@ async function setupVM(code: Buffer) { tape('EIP-3074 AUTHCALL', (t) => { t.test('Should execute AUTHCALL correctly', async (st) => { - const message = Buffer.from('01', 'hex') + const message = hexToBytes('01') const signature = signMessage(message, contractAddress, privateKey) - const code = Buffer.concat([ + const code = concatBytesNoTypeCheck( getAuthCode(message, signature, authAddress), getAuthCallCode({ address: contractStorageAddress, }), - RETURNTOP, - ]) + RETURNTOP + ) const vm = await setupVM(code) const tx = Transaction.fromTxData({ @@ -440,22 +441,22 @@ tape('EIP-3074 AUTHCALL', (t) => { const result = await vm.runTx({ tx, block, skipHardForkValidation: true }) const buf = result.execResult.returnValue.slice(31) - st.ok(buf.equals(Buffer.from('01', 'hex')), 'authcall success') + st.deepEquals(buf, hexToBytes('01'), 'authcall success') const storage = await vm.stateManager.getContractStorage(contractStorageAddress, zeros(32)) - st.ok(storage.equals(address.buf), 'caller set correctly') + st.deepEquals(storage, address.bytes, 'caller set correctly') }) t.test('Should forward max call gas when gas set to 0', async (st) => { - const message = Buffer.from('01', 'hex') + const message = hexToBytes('01') const signature = signMessage(message, contractAddress, privateKey) - const code = Buffer.concat([ + const code = concatBytesNoTypeCheck( getAuthCode(message, signature, authAddress), getAuthCallCode({ address: contractStorageAddress, }), - RETURNTOP, - ]) + RETURNTOP + ) const vm = await setupVM(code) let gas: bigint @@ -475,9 +476,9 @@ tape('EIP-3074 AUTHCALL', (t) => { const gasUsed = await vm.stateManager.getContractStorage( contractStorageAddress, - Buffer.from('00'.repeat(31) + '01', 'hex') + hexToBytes('00'.repeat(31) + '01') ) - const gasBigInt = bufferToBigInt(gasUsed) + const gasBigInt = bytesToBigInt(gasUsed) const preGas = gas! - common.param('gasPrices', 'warmstorageread')! - @@ -487,9 +488,9 @@ tape('EIP-3074 AUTHCALL', (t) => { }) t.test('Should forward max call gas when gas set to 0 - warm account', async (st) => { - const message = Buffer.from('01', 'hex') + const message = hexToBytes('01') const signature = signMessage(message, contractAddress, privateKey) - const code = Buffer.concat([ + const code = concatBytesNoTypeCheck( getAuthCode(message, signature, authAddress), getAuthCallCode({ address: contractStorageAddress, @@ -497,8 +498,8 @@ tape('EIP-3074 AUTHCALL', (t) => { getAuthCallCode({ address: contractStorageAddress, }), - RETURNTOP, - ]) + RETURNTOP + ) const vm = await setupVM(code) let gas: bigint @@ -518,9 +519,9 @@ tape('EIP-3074 AUTHCALL', (t) => { const gasUsed = await vm.stateManager.getContractStorage( contractStorageAddress, - Buffer.from('00'.repeat(31) + '01', 'hex') + hexToBytes('00'.repeat(31) + '01') ) - const gasBigInt = bufferToBigInt(gasUsed) + const gasBigInt = bytesToBigInt(gasUsed) const preGas = gas! - common.param('gasPrices', 'warmstorageread')! const expected = preGas - preGas / 64n - 2n st.equal(gasBigInt, expected, 'forwarded max call gas') @@ -529,16 +530,16 @@ tape('EIP-3074 AUTHCALL', (t) => { t.test( 'Should forward max call gas when gas set to 0 - cold account, nonzero transfer, create new account', async (st) => { - const message = Buffer.from('01', 'hex') + const message = hexToBytes('01') const signature = signMessage(message, contractAddress, privateKey) - const code = Buffer.concat([ + const code = concatBytesNoTypeCheck( getAuthCode(message, signature, authAddress), getAuthCallCode({ - address: new Address(Buffer.from('cc'.repeat(20), 'hex')), + address: new Address(hexToBytes('cc'.repeat(20))), value: 1n, }), - RETURNTOP, - ]) + RETURNTOP + ) const vm = await setupVM(code) let gas: bigint @@ -575,16 +576,16 @@ tape('EIP-3074 AUTHCALL', (t) => { t.test( 'Should charge value transfer gas when transferring and transfer from contract, not authcall address', async (st) => { - const message = Buffer.from('01', 'hex') + const message = hexToBytes('01') const signature = signMessage(message, contractAddress, privateKey) - const code = Buffer.concat([ + const code = concatBytesNoTypeCheck( getAuthCode(message, signature, authAddress), getAuthCallCode({ address: contractStorageAddress, value: 1n, }), - RETURNTOP, - ]) + RETURNTOP + ) const vm = await setupVM(code) let gas: bigint @@ -608,9 +609,9 @@ tape('EIP-3074 AUTHCALL', (t) => { const gasUsed = await vm.stateManager.getContractStorage( contractStorageAddress, - Buffer.from('00'.repeat(31) + '01', 'hex') + hexToBytes('00'.repeat(31) + '01') ) - const gasBigInt = bufferToBigInt(gasUsed) + const gasBigInt = bytesToBigInt(gasUsed) const preGas = gas! - common.param('gasPrices', 'warmstorageread')! - @@ -633,12 +634,12 @@ tape('EIP-3074 AUTHCALL', (t) => { ) t.test('Should throw if AUTH not set', async (st) => { - const code = Buffer.concat([ + const code = concatBytesNoTypeCheck( getAuthCallCode({ address: contractStorageAddress, }), - RETURNTOP, - ]) + RETURNTOP + ) const vm = await setupVM(code) const tx = Transaction.fromTxData({ @@ -657,14 +658,14 @@ tape('EIP-3074 AUTHCALL', (t) => { }) t.test('Should unset AUTH in case of invalid signature', async (st) => { - const message = Buffer.from('01', 'hex') + const message = hexToBytes('01') const signature = signMessage(message, contractAddress, privateKey) const signature2 = { v: signature.v, r: signature.s, s: signature.s, } - const code = Buffer.concat([ + const code = concatBytesNoTypeCheck( getAuthCode(message, signature, authAddress), getAuthCallCode({ address: contractStorageAddress, @@ -673,8 +674,8 @@ tape('EIP-3074 AUTHCALL', (t) => { getAuthCallCode({ address: contractStorageAddress, }), - RETURNTOP, - ]) + RETURNTOP + ) const vm = await setupVM(code) const tx = Transaction.fromTxData({ @@ -693,16 +694,16 @@ tape('EIP-3074 AUTHCALL', (t) => { }) t.test('Should throw if not enough gas is available', async (st) => { - const message = Buffer.from('01', 'hex') + const message = hexToBytes('01') const signature = signMessage(message, contractAddress, privateKey) - const code = Buffer.concat([ + const code = concatBytesNoTypeCheck( getAuthCode(message, signature, authAddress), getAuthCallCode({ address: contractStorageAddress, gasLimit: 10000000n, }), - RETURNTOP, - ]) + RETURNTOP + ) const vm = await setupVM(code) const tx = Transaction.fromTxData({ @@ -717,16 +718,16 @@ tape('EIP-3074 AUTHCALL', (t) => { }) t.test('Should throw if valueExt is nonzero', async (st) => { - const message = Buffer.from('01', 'hex') + const message = hexToBytes('01') const signature = signMessage(message, contractAddress, privateKey) - const code = Buffer.concat([ + const code = concatBytesNoTypeCheck( getAuthCode(message, signature, authAddress), getAuthCallCode({ address: contractStorageAddress, valueExt: 1n, }), - RETURNTOP, - ]) + RETURNTOP + ) const vm = await setupVM(code) const tx = Transaction.fromTxData({ @@ -745,16 +746,16 @@ tape('EIP-3074 AUTHCALL', (t) => { }) t.test('Should forward the right amount of gas', async (st) => { - const message = Buffer.from('01', 'hex') + const message = hexToBytes('01') const signature = signMessage(message, contractAddress, privateKey) - const code = Buffer.concat([ + const code = concatBytesNoTypeCheck( getAuthCode(message, signature, authAddress), getAuthCallCode({ address: contractStorageAddress, gasLimit: 700000n, }), - RETURNTOP, - ]) + RETURNTOP + ) const vm = await setupVM(code) const tx = Transaction.fromTxData({ @@ -766,19 +767,19 @@ tape('EIP-3074 AUTHCALL', (t) => { await vm.runTx({ tx, block, skipHardForkValidation: true }) const gas = await vm.stateManager.getContractStorage( contractStorageAddress, - Buffer.from('00'.repeat(31) + '01', 'hex') + hexToBytes('00'.repeat(31) + '01') ) - const gasBigInt = bufferToBigInt(gas) + const gasBigInt = bytesToBigInt(gas) st.equals(gasBigInt, BigInt(700000 - 2), 'forwarded the right amount of gas') // The 2 is subtracted due to the GAS opcode base fee }) t.test('Should set input and output correctly', async (st) => { - const message = Buffer.from('01', 'hex') + const message = hexToBytes('01') const signature = signMessage(message, contractAddress, privateKey) - const input = Buffer.from('aa'.repeat(32), 'hex') - const code = Buffer.concat([ + const input = hexToBytes('aa'.repeat(32)) + const code = concatBytesNoTypeCheck( getAuthCode(message, signature, authAddress), - MSTORE(Buffer.from('20', 'hex'), input), + MSTORE(hexToBytes('20'), input), getAuthCallCode({ address: contractStorageAddress, argsOffset: 32n, @@ -786,8 +787,8 @@ tape('EIP-3074 AUTHCALL', (t) => { retOffset: 64n, retLength: 32n, }), - Buffer.from('60206040F3', 'hex'), // PUSH 32 PUSH 64 RETURN -> This returns the 32 bytes at memory position 64 - ]) + hexToBytes('60206040F3') // PUSH 32 PUSH 64 RETURN -> This returns the 32 bytes at memory position 64 + ) const vm = await setupVM(code) const tx = Transaction.fromTxData({ @@ -799,9 +800,9 @@ tape('EIP-3074 AUTHCALL', (t) => { const result = await vm.runTx({ tx, block, skipHardForkValidation: true }) const callInput = await vm.stateManager.getContractStorage( contractStorageAddress, - Buffer.from('00'.repeat(31) + '02', 'hex') + hexToBytes('00'.repeat(31) + '02') ) - st.ok(callInput.equals(input), 'authcall input ok') - st.ok(result.execResult.returnValue.equals(input), 'authcall output ok') + st.deepEquals(callInput, input, 'authcall input ok') + st.deepEquals(result.execResult.returnValue, input, 'authcall output ok') }) }) diff --git a/packages/vm/test/api/EIPs/eip-3198-BaseFee.spec.ts b/packages/vm/test/api/EIPs/eip-3198-BaseFee.spec.ts index 15327409cc..2cc2ef8611 100644 --- a/packages/vm/test/api/EIPs/eip-3198-BaseFee.spec.ts +++ b/packages/vm/test/api/EIPs/eip-3198-BaseFee.spec.ts @@ -2,6 +2,7 @@ import { Block } from '@ethereumjs/block' import { Chain, Common, Hardfork } from '@ethereumjs/common' import { FeeMarketEIP1559Transaction } from '@ethereumjs/tx' import { Address, privateToAddress } from '@ethereumjs/util' +import { hexToBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' import { VM } from '../../../src/vm' @@ -30,8 +31,8 @@ common.hardforkBlock = function (hardfork: string | undefined) { return BigInt(0) } -const coinbase = new Address(Buffer.from('11'.repeat(20), 'hex')) -const pkey = Buffer.from('20'.repeat(32), 'hex') +const coinbase = new Address(hexToBytes('11'.repeat(20))) +const pkey = hexToBytes('20'.repeat(32)) const sender = new Address(privateToAddress(pkey)) /** diff --git a/packages/vm/test/api/EIPs/eip-3529.spec.ts b/packages/vm/test/api/EIPs/eip-3529.spec.ts index 17a1763887..2e221a0c5c 100644 --- a/packages/vm/test/api/EIPs/eip-3529.spec.ts +++ b/packages/vm/test/api/EIPs/eip-3529.spec.ts @@ -1,14 +1,15 @@ import { Chain, Common, Hardfork } from '@ethereumjs/common' import { Transaction } from '@ethereumjs/tx' import { Address } from '@ethereumjs/util' +import { hexToBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' import { VM } from '../../../src/vm' import type { InterpreterStep } from '@ethereumjs/evm/dist/interpreter' -const address = new Address(Buffer.from('11'.repeat(20), 'hex')) -const pkey = Buffer.from('20'.repeat(32), 'hex') +const address = new Address(hexToBytes('11'.repeat(20))) +const pkey = hexToBytes('20'.repeat(32)) const testCases = [ { @@ -125,19 +126,19 @@ tape('EIP-3529 tests', (t) => { }) const gasLimit = BigInt(100000) - const key = Buffer.from('00'.repeat(32), 'hex') + const key = hexToBytes('00'.repeat(32)) for (const testCase of testCases) { - const code = Buffer.from((testCase.code + '00').slice(2), 'hex') // add a STOP opcode (0 gas) so we can find the gas used / effective gas + const code = hexToBytes((testCase.code + '00').slice(2)) // add a STOP opcode (0 gas) so we can find the gas used / effective gas await vm.stateManager.putContractStorage( address, key, - Buffer.from(testCase.original.toString().padStart(64, '0'), 'hex') + hexToBytes(testCase.original.toString().padStart(64, '0')) ) await vm.stateManager.getContractStorage(address, key) - vm.eei.addWarmedStorage(address.toBuffer(), key) + vm.eei.addWarmedStorage(address.toBytes(), key) await vm.evm.runCode!({ code, @@ -194,14 +195,14 @@ tape('EIP-3529 tests', (t) => { } }) - const address = new Address(Buffer.from('20'.repeat(20), 'hex')) + const address = new Address(hexToBytes('20'.repeat(20))) - const value = Buffer.from('01'.repeat(32), 'hex') + const value = hexToBytes('01'.repeat(32)) let code = '' for (let i = 0; i < 100; i++) { - const key = Buffer.from(i.toString(16).padStart(64, '0'), 'hex') + const key = hexToBytes(i.toString(16).padStart(64, '0')) await vm.stateManager.putContractStorage(address, key, value) const hex = i.toString(16).padStart(2, '0') // push 0 push sstore @@ -210,7 +211,7 @@ tape('EIP-3529 tests', (t) => { code += '00' - await vm.stateManager.putContractCode(address, Buffer.from(code, 'hex')) + await vm.stateManager.putContractCode(address, hexToBytes(code)) const tx = Transaction.fromTxData({ to: address, diff --git a/packages/vm/test/api/EIPs/eip-3540-evm-object-format.spec.ts b/packages/vm/test/api/EIPs/eip-3540-evm-object-format.spec.ts index 10ca8e1709..1bfc0a075e 100644 --- a/packages/vm/test/api/EIPs/eip-3540-evm-object-format.spec.ts +++ b/packages/vm/test/api/EIPs/eip-3540-evm-object-format.spec.ts @@ -1,12 +1,13 @@ import { Chain, Common, Hardfork } from '@ethereumjs/common' import { EOF } from '@ethereumjs/evm/dist/eof' import { FeeMarketEIP1559Transaction } from '@ethereumjs/tx' -import { Address, privateToAddress } from '@ethereumjs/util' +import { Address, concatBytesNoTypeCheck, privateToAddress } from '@ethereumjs/util' +import { hexToBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' import { VM } from '../../../src/vm' -const pkey = Buffer.from('20'.repeat(32), 'hex') +const pkey = hexToBytes('20'.repeat(32)) const GWEI = BigInt('1000000000') const sender = new Address(privateToAddress(pkey)) @@ -31,29 +32,36 @@ tape('EIP 3540 tests', (t) => { }) t.test('EOF > codeAnalysis() tests', async (st) => { - const eofHeader = Buffer.from([EOF.FORMAT, EOF.MAGIC, EOF.VERSION]) + const eofHeader = Uint8Array.from([EOF.FORMAT, EOF.MAGIC, EOF.VERSION]) st.ok( - EOF.codeAnalysis(Buffer.concat([eofHeader, Uint8Array.from([0x01, 0x00, 0x01, 0x00, 0x00])])) - ?.code! > 0, + EOF.codeAnalysis( + concatBytesNoTypeCheck(eofHeader, Uint8Array.from([0x01, 0x00, 0x01, 0x00, 0x00])) + )?.code! > 0, 'valid code section' ) st.ok( EOF.codeAnalysis( - Buffer.concat([ + concatBytesNoTypeCheck( eofHeader, - Uint8Array.from([0x01, 0x00, 0x01, 0x02, 0x00, 0x01, 0x00, 0x00, 0xaa]), - ]) + Uint8Array.from([0x01, 0x00, 0x01, 0x02, 0x00, 0x01, 0x00, 0x00, 0xaa]) + ) )?.data! > 0, 'valid data section' ) st.ok( - !EOF.codeAnalysis( - Buffer.concat([eofHeader, Uint8Array.from([0x01, 0x00, 0x01, 0x00, 0x00, 0x00])]) + !( + EOF.codeAnalysis( + concatBytesNoTypeCheck(eofHeader, Uint8Array.from([0x01, 0x00, 0x01, 0x00, 0x00, 0x00])) + ) !== undefined ), 'invalid container length (too long)' ) st.ok( - !EOF.codeAnalysis(Buffer.concat([eofHeader, Uint8Array.from([0x01, 0x00, 0x01, 0x00])])), + !( + EOF.codeAnalysis( + concatBytesNoTypeCheck(eofHeader, Uint8Array.from([0x01, 0x00, 0x01, 0x00])) + ) !== undefined + ), 'invalid container length (too short)' ) st.end() diff --git a/packages/vm/test/api/EIPs/eip-3541.spec.ts b/packages/vm/test/api/EIPs/eip-3541.spec.ts index eeee576072..d66e2b8d2a 100644 --- a/packages/vm/test/api/EIPs/eip-3541.spec.ts +++ b/packages/vm/test/api/EIPs/eip-3541.spec.ts @@ -1,5 +1,6 @@ import { Chain, Common, Hardfork } from '@ethereumjs/common' import { Transaction } from '@ethereumjs/tx' +import { hexToBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' import { VM } from '../../../src/vm' @@ -7,7 +8,7 @@ import { VM } from '../../../src/vm' import type { InterpreterStep } from '@ethereumjs/evm/dist/interpreter' import type { Address } from '@ethereumjs/util' -const pkey = Buffer.from('20'.repeat(32), 'hex') +const pkey = hexToBytes('20'.repeat(32)) tape('EIP 3541 tests', (t) => { const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Berlin, eips: [3541] }) diff --git a/packages/vm/test/api/EIPs/eip-3607.spec.ts b/packages/vm/test/api/EIPs/eip-3607.spec.ts index b7907ab719..accea3dadc 100644 --- a/packages/vm/test/api/EIPs/eip-3607.spec.ts +++ b/packages/vm/test/api/EIPs/eip-3607.spec.ts @@ -12,7 +12,7 @@ tape('EIP-3607 tests', (t) => { t.test('should reject txs from senders with deployed code when EIP is enabled', async (st) => { const vm = await VM.create({ common }) - await vm.stateManager.putContractCode(precompileAddr, Buffer.alloc(32, 1)) + await vm.stateManager.putContractCode(precompileAddr, new Uint8Array(32).fill(1)) const tx = Transaction.fromTxData({ gasLimit: 100000 }, { freeze: false }) tx.getSenderAddress = () => precompileAddr try { @@ -32,7 +32,7 @@ tape('EIP-3607 tests', (t) => { 'should not reject txs from senders with deployed code when EIP is not enabled', async (st) => { const vm = await VM.create({ common: commonNoEIP3607 }) - await vm.stateManager.putContractCode(precompileAddr, Buffer.alloc(32, 1)) + await vm.stateManager.putContractCode(precompileAddr, new Uint8Array(32).fill(1)) const tx = Transaction.fromTxData({ gasLimit: 100000 }, { freeze: false }) tx.getSenderAddress = () => precompileAddr try { diff --git a/packages/vm/test/api/EIPs/eip-3651-warm-coinbase.spec.ts b/packages/vm/test/api/EIPs/eip-3651-warm-coinbase.spec.ts index 33ebd2711c..cfb6338094 100644 --- a/packages/vm/test/api/EIPs/eip-3651-warm-coinbase.spec.ts +++ b/packages/vm/test/api/EIPs/eip-3651-warm-coinbase.spec.ts @@ -2,14 +2,15 @@ import { Block } from '@ethereumjs/block' import { Chain, Common, Hardfork } from '@ethereumjs/common' import { Transaction } from '@ethereumjs/tx' import { Address, privateToAddress } from '@ethereumjs/util' +import { hexToBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' import { VM } from '../../../src/vm' -const pkey = Buffer.from('20'.repeat(32), 'hex') +const pkey = hexToBytes('20'.repeat(32)) const GWEI = BigInt(1000000000) const sender = new Address(privateToAddress(pkey)) -const coinbase = new Address(Buffer.from('ff'.repeat(20), 'hex')) +const coinbase = new Address(hexToBytes('ff'.repeat(20))) const common = new Common({ chain: Chain.Mainnet, @@ -27,8 +28,8 @@ const block = Block.fromBlockData( { common } ) -const code = Buffer.from('60008080806001415AF100', 'hex') -const contractAddress = new Address(Buffer.from('ee'.repeat(20), 'hex')) +const code = hexToBytes('60008080806001415AF100') +const contractAddress = new Address(hexToBytes('ee'.repeat(20))) async function getVM(common: Common) { const vm = await VM.create({ common }) diff --git a/packages/vm/test/api/EIPs/eip-3670-eof-code-validation.spec.ts b/packages/vm/test/api/EIPs/eip-3670-eof-code-validation.spec.ts index 01565c4cba..04ecdb4631 100644 --- a/packages/vm/test/api/EIPs/eip-3670-eof-code-validation.spec.ts +++ b/packages/vm/test/api/EIPs/eip-3670-eof-code-validation.spec.ts @@ -2,10 +2,11 @@ import { Chain, Common, Hardfork } from '@ethereumjs/common' import { EOF } from '@ethereumjs/evm/dist/eof' import { FeeMarketEIP1559Transaction } from '@ethereumjs/tx' import { Address, privateToAddress } from '@ethereumjs/util' +import { hexToBytes, utf8ToBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' import { VM } from '../../../src/vm' -const pkey = Buffer.from('20'.repeat(32), 'hex') +const pkey = hexToBytes('20'.repeat(32)) const GWEI = BigInt('1000000000') const sender = new Address(privateToAddress(pkey)) @@ -30,28 +31,28 @@ tape('EIP 3670 tests', (t) => { }) t.test('EOF > validOpcodes() tests', (st) => { - st.ok(EOF.validOpcodes(Buffer.from([0])), 'valid -- STOP ') - st.ok(EOF.validOpcodes(Buffer.from([0xfe])), 'valid -- INVALID opcode') - st.ok(EOF.validOpcodes(Buffer.from([0x60, 0xaa, 0])), 'valid - PUSH1 AA STOP') + st.ok(EOF.validOpcodes(Uint8Array.from([0])), 'valid -- STOP ') + st.ok(EOF.validOpcodes(Uint8Array.from([0xfe])), 'valid -- INVALID opcode') + st.ok(EOF.validOpcodes(Uint8Array.from([0x60, 0xaa, 0])), 'valid - PUSH1 AA STOP') for (const opcode of [0x00, 0xf3, 0xfd, 0xfe, 0xff]) { st.ok( - EOF.validOpcodes(Buffer.from([0x60, 0xaa, opcode])), + EOF.validOpcodes(Uint8Array.from([0x60, 0xaa, opcode])), `code ends with valid terminating instruction 0x${opcode.toString(16)}` ) } - st.notOk(EOF.validOpcodes(Buffer.from([0xaa])), 'invalid -- AA -- undefined opcode') + st.notOk(EOF.validOpcodes(Uint8Array.from([0xaa])), 'invalid -- AA -- undefined opcode') st.notOk( - EOF.validOpcodes(Buffer.from([0x7f, 0xaa, 0])), + EOF.validOpcodes(Uint8Array.from([0x7f, 0xaa, 0])), 'invalid -- PUSH32 AA STOP -- truncated push' ) st.notOk( - EOF.validOpcodes(Buffer.from([0x61, 0xaa, 0])), + EOF.validOpcodes(Uint8Array.from([0x61, 0xaa, 0])), 'invalid -- PUSH2 AA STOP -- truncated push' ) st.notOk( - EOF.validOpcodes(Buffer.from([0x60, 0xaa, 0x30])), + EOF.validOpcodes(Uint8Array.from([0x60, 0xaa, 0x30])), 'invalid -- PUSH1 AA ADDRESS -- invalid terminal opcode' ) st.end() @@ -98,31 +99,29 @@ tape('EIP 3670 tests', (t) => { const vm = await VM.create({ common }) // Valid EOF code - const codeValid = Buffer.from( - 'ef000101008102000c006080604052348015600f57600080fd5b506004361060285760003560e01c8063f8a8fd6d14602d575b600080fd5b60336047565b604051603e91906067565b60405180910390f35b6000602a905090565b6000819050919050565b6061816050565b82525050565b6000602082019050607a6000830184605a565b92915050560048656c6c6f20576f726c6421', - 'hex' + const codeValid = hexToBytes( + 'ef000101008102000c006080604052348015600f57600080fd5b506004361060285760003560e01c8063f8a8fd6d14602d575b600080fd5b60336047565b604051603e91906067565b60405180910390f35b6000602a905090565b6000819050919050565b6061816050565b82525050565b6000602082019050607a6000830184605a565b92915050560048656c6c6f20576f726c6421' ) // Invalid EOF code: code is exactly the same except the byte at the zero-index is not the FORMAT magic // This thus runs into opcode 0xED which is unassigned and thus invalid - const codeInvalid = Buffer.from( - 'ed000101008102000c006080604052348015600f57600080fd5b506004361060285760003560e01c8063f8a8fd6d14602d575b600080fd5b60336047565b604051603e91906067565b60405180910390f35b6000602a905090565b6000819050919050565b6061816050565b82525050565b6000602082019050607a6000830184605a565b92915050560048656c6c6f20576f726c6421', - 'hex' + const codeInvalid = hexToBytes( + 'ed000101008102000c006080604052348015600f57600080fd5b506004361060285760003560e01c8063f8a8fd6d14602d575b600080fd5b60336047565b604051603e91906067565b60405180910390f35b6000602a905090565b6000819050919050565b6061816050565b82525050565b6000602082019050607a6000830184605a565b92915050560048656c6c6f20576f726c6421' ) const codes = [codeValid, codeInvalid] const returnValues = [ - Buffer.from('000000000000000000000000000000000000000000000000000000000000002a', 'hex'), - Buffer.from(''), + hexToBytes('000000000000000000000000000000000000000000000000000000000000002a'), + utf8ToBytes(''), ] const expectedErrors = [false, true] let nonce = 0n for (let i = 0; i < codes.length; i++) { - const calldata = Buffer.from('f8a8fd6d', 'hex') + const calldata = hexToBytes('f8a8fd6d') - const addr = new Address(Buffer.from('20'.repeat(20), 'hex')) - const pkey = Buffer.from('42'.repeat(32), 'hex') + const addr = new Address(hexToBytes('20'.repeat(20))) + const pkey = hexToBytes('42'.repeat(32)) const code = codes[i] @@ -150,7 +149,7 @@ tape('EIP 3670 tests', (t) => { const expectReturn = returnValues[i] const expectError = expectedErrors[i] - st.ok(ret.execResult.returnValue.equals(expectReturn), 'return value ok') + st.deepEquals(ret.execResult.returnValue, expectReturn, 'return value ok') if (expectError) { st.ok(ret.execResult.exceptionError !== undefined, 'threw error') } else { diff --git a/packages/vm/test/api/EIPs/eip-3855.spec.ts b/packages/vm/test/api/EIPs/eip-3855.spec.ts index 92ab9a94d6..872ada800a 100644 --- a/packages/vm/test/api/EIPs/eip-3855.spec.ts +++ b/packages/vm/test/api/EIPs/eip-3855.spec.ts @@ -1,5 +1,6 @@ import { Chain, Common, Hardfork } from '@ethereumjs/common' import { ERROR } from '@ethereumjs/evm/dist/exceptions' +import { hexToBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' import { VM } from '../../../src/vm' @@ -25,7 +26,7 @@ tape('EIP 3541 tests', (t) => { }) const result = await vm.evm.runCode!({ - code: Buffer.from('5F', 'hex'), + code: hexToBytes('5F'), gasLimit: BigInt(10), }) @@ -45,7 +46,7 @@ tape('EIP 3541 tests', (t) => { const depth = Number(common.param('vm', 'stackLimit')) const result = await vm.evm.runCode!({ - code: Buffer.from('5F'.repeat(depth), 'hex'), + code: hexToBytes('5F'.repeat(depth)), gasLimit: BigInt(10000), }) @@ -65,7 +66,7 @@ tape('EIP 3541 tests', (t) => { const depth = Number(common.param('vm', 'stackLimit')!) + 1 const result = await vm.evm.runCode!({ - code: Buffer.from('5F'.repeat(depth), 'hex'), + code: hexToBytes('5F'.repeat(depth)), gasLimit: BigInt(10000), }) @@ -77,7 +78,7 @@ tape('EIP 3541 tests', (t) => { const vm = await VM.create({ common: commonNoEIP3855 }) const result = await vm.evm.runCode!({ - code: Buffer.from('5F', 'hex'), + code: hexToBytes('5F'), gasLimit: BigInt(10000), }) diff --git a/packages/vm/test/api/EIPs/eip-3860.spec.ts b/packages/vm/test/api/EIPs/eip-3860.spec.ts index f5fb84f88e..12d138381b 100644 --- a/packages/vm/test/api/EIPs/eip-3860.spec.ts +++ b/packages/vm/test/api/EIPs/eip-3860.spec.ts @@ -1,10 +1,11 @@ import { Chain, Common, Hardfork } from '@ethereumjs/common' import { FeeMarketEIP1559Transaction } from '@ethereumjs/tx' import { Address, privateToAddress } from '@ethereumjs/util' +import { bytesToHex, hexToBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' import { VM } from '../../../src/vm' -const pkey = Buffer.from('20'.repeat(32), 'hex') +const pkey = hexToBytes('20'.repeat(32)) const GWEI = BigInt('1000000000') const sender = new Address(privateToAddress(pkey)) @@ -22,11 +23,11 @@ tape('EIP 3860 tests', (t) => { account.balance = balance await vm.stateManager.putAccount(sender, account) - const buffer = Buffer.allocUnsafe(1000000).fill(0x60) + const bytes = new Uint8Array(1000000).fill(0x60) const tx = FeeMarketEIP1559Transaction.fromTxData({ data: '0x7F6000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060005260206000F3' + - buffer.toString('hex'), + bytesToHex(bytes), gasLimit: 100000000000, maxFeePerGas: 7, nonce: 0, diff --git a/packages/vm/test/api/EIPs/eip-4399-supplant-difficulty-opcode-with-prevrando.spec.ts b/packages/vm/test/api/EIPs/eip-4399-supplant-difficulty-opcode-with-prevrando.spec.ts index a0ef7ce9c2..6e47a039b0 100644 --- a/packages/vm/test/api/EIPs/eip-4399-supplant-difficulty-opcode-with-prevrando.spec.ts +++ b/packages/vm/test/api/EIPs/eip-4399-supplant-difficulty-opcode-with-prevrando.spec.ts @@ -1,6 +1,7 @@ import { Block } from '@ethereumjs/block' import { Chain, Common, Hardfork } from '@ethereumjs/common' -import { bufferToBigInt } from '@ethereumjs/util' +import { bytesToBigInt } from '@ethereumjs/util' +import { hexToBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' import { VM } from '../../../src/vm' @@ -33,14 +34,14 @@ tape('EIP-4399 -> 0x44 (DIFFICULTY) should return PREVRANDAO', (t) => { }) const runCodeArgs = { - code: Buffer.from('4400', 'hex'), + code: hexToBytes('4400'), gasLimit: BigInt(0xffff), } await vm.evm.runCode!({ ...runCodeArgs, block }) st.equal(stack[0], block.header.difficulty, '0x44 returns DIFFICULTY (London)') common.setHardfork(Hardfork.Merge) - const prevRandao = bufferToBigInt(Buffer.alloc(32, 1)) + const prevRandao = bytesToBigInt(new Uint8Array(32).fill(1)) block = Block.fromBlockData( { header: { diff --git a/packages/vm/test/api/EIPs/eip-4895-withdrawals.spec.ts b/packages/vm/test/api/EIPs/eip-4895-withdrawals.spec.ts index 72b7ef30d8..06ce01077e 100644 --- a/packages/vm/test/api/EIPs/eip-4895-withdrawals.spec.ts +++ b/packages/vm/test/api/EIPs/eip-4895-withdrawals.spec.ts @@ -4,12 +4,13 @@ import { Chain, Common, Hardfork } from '@ethereumjs/common' import { decode } from '@ethereumjs/rlp' import { FeeMarketEIP1559Transaction } from '@ethereumjs/tx' import { Address, GWEI_TO_WEI, KECCAK256_RLP, Withdrawal, zeros } from '@ethereumjs/util' +import { bytesToHex, hexToBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' import genesisJSON = require('../../../../client/test/testdata/geth-genesis/withdrawals.json') import { VM } from '../../../src/vm' -import type { WithdrawalBuffer, WithdrawalData } from '@ethereumjs/util' +import type { WithdrawalBytes, WithdrawalData } from '@ethereumjs/util' const common = new Common({ chain: Chain.Mainnet, @@ -17,7 +18,7 @@ const common = new Common({ eips: [4895], }) -const pkey = Buffer.from('20'.repeat(32), 'hex') +const pkey = hexToBytes('20'.repeat(32)) const gethWithdrawals8BlockRlp = 'f903e1f90213a0fe950635b1bd2a416ff6283b0bbd30176e1b1125ad06fa729da9f3f4c1c61710a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794aa00000000000000000000000000000000000000a07f7510a0cb6203f456e34ec3e2ce30d6c5590ded42c10a9cf3f24784119c5afba056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080018401c9c380802f80a0ff0000000000000000000000000000000000000000000000000000000000000088000000000000000007a0b695b29ec7ee934ef6a68838b13729f2d49fffe26718de16a1a9ed94a4d7d06dc0c0f901c6da8082ffff94000000000000000000000000000000000000000080f83b0183010000940100000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f83b0283010001940200000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f83b0383010002940300000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f83b0483010003940400000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f83b0583010004940500000000000000000000000000000000000000a00500000000000000000000000000000000000000000000000000000000000000f83b0683010005940600000000000000000000000000000000000000a00600000000000000000000000000000000000000000000000000000000000000f83b0783010006940700000000000000000000000000000000000000a00700000000000000000000000000000000000000000000000000000000000000' @@ -35,12 +36,12 @@ tape('EIP4895 tests', (t) => { SSTORE If code is ran, this stores "2" at slot "0". Check if withdrawal operations do not invoke this code */ - const withdrawalCheckAddress = new Address(Buffer.from('fe'.repeat(20), 'hex')) - const withdrawalCode = Buffer.from('6002600055') + const withdrawalCheckAddress = new Address(hexToBytes('fe'.repeat(20))) + const withdrawalCode = hexToBytes('6002600055') await vm.stateManager.putContractCode(withdrawalCheckAddress, withdrawalCode) - const contractAddress = new Address(Buffer.from('ff'.repeat(20), 'hex')) + const contractAddress = new Address(hexToBytes('ff'.repeat(20))) /* PUSH @@ -52,7 +53,7 @@ tape('EIP4895 tests', (t) => { RETURN // Return the balance */ const contract = '73' + addresses[0] + '3160005260206000F3' - await vm.stateManager.putContractCode(contractAddress, Buffer.from(contract, 'hex')) + await vm.stateManager.putContractCode(contractAddress, hexToBytes(contract)) const transaction = FeeMarketEIP1559Transaction.fromTxData({ to: contractAddress, @@ -71,7 +72,7 @@ tape('EIP4895 tests', (t) => { withdrawals.push({ index, validatorIndex: index, - address: new Address(Buffer.from(addresses[i], 'hex')), + address: new Address(hexToBytes(addresses[i])), amount: amounts[i], }) index++ @@ -80,13 +81,11 @@ tape('EIP4895 tests', (t) => { { header: { baseFeePerGas: BigInt(7), - withdrawalsRoot: Buffer.from( - '267414525d22e2be123b619719b92c561f31e0cdd40959148230f5713aecd6b8', - 'hex' + withdrawalsRoot: hexToBytes( + '267414525d22e2be123b619719b92c561f31e0cdd40959148230f5713aecd6b8' ), - transactionsTrie: Buffer.from( - '9a744e8acc2886e5809ff013e3b71bf8ec97f9941cafbd7730834fc8f76391ba', - 'hex' + transactionsTrie: hexToBytes( + '9a744e8acc2886e5809ff013e3b71bf8ec97f9941cafbd7730834fc8f76391ba' ), }, transactions: [transaction], @@ -95,7 +94,7 @@ tape('EIP4895 tests', (t) => { { common: vm._common } ) - let result: Buffer + let result: Uint8Array vm.events.on('afterTx', (e) => { result = e.execResult.returnValue }) @@ -103,31 +102,31 @@ tape('EIP4895 tests', (t) => { await vm.runBlock({ block, generate: true }) for (let i = 0; i < addresses.length; i++) { - const address = new Address(Buffer.from(addresses[i], 'hex')) + const address = new Address(hexToBytes(addresses[i])) const amount = amounts[i] const balance = (await vm.stateManager.getAccount(address)).balance st.equals(BigInt(amount) * GWEI_TO_WEI, balance, 'balance ok') } - st.ok(zeros(32).equals(result!), 'withdrawals happen after transactions') + st.deepEquals(zeros(32), result!, 'withdrawals happen after transactions') const slotValue = await vm.stateManager.getContractStorage(withdrawalCheckAddress, zeros(32)) - st.ok(zeros(0).equals(slotValue), 'withdrawals do not invoke code') + st.deepEquals(zeros(0), slotValue, 'withdrawals do not invoke code') }) t.test('EIP4895: state updation should exclude 0 amount updates', async (st) => { const vm = await VM.create({ common }) await vm.eei.generateCanonicalGenesis(parseGethGenesisState(genesisJSON)) - const preState = (await vm.eei.getStateRoot()).toString('hex') + const preState = bytesToHex(await vm.eei.getStateRoot()) st.equal( preState, 'ca3149fa9e37db08d1cd49c9061db1002ef1cd58db2210f2115c8c989b2bdf45', 'preState should be correct' ) - const gethBlockBufferArray = decode(Buffer.from(gethWithdrawals8BlockRlp, 'hex')) - const withdrawals = (gethBlockBufferArray[3] as WithdrawalBuffer[]).map((wa) => + const gethBlockBufferArray = decode(hexToBytes(gethWithdrawals8BlockRlp)) + const withdrawals = (gethBlockBufferArray[3] as WithdrawalBytes[]).map((wa) => Withdrawal.fromValuesArray(wa) ) st.equal(withdrawals[0].amount, BigInt(0), 'withdrawal 0 should have 0 amount') @@ -147,7 +146,7 @@ tape('EIP4895 tests', (t) => { }, { common: vm._common } ) - postState = (await vm.eei.getStateRoot()).toString('hex') + postState = bytesToHex(await vm.eei.getStateRoot()) await vm.runBlock({ block, generate: true }) st.equal( @@ -170,7 +169,7 @@ tape('EIP4895 tests', (t) => { { common: vm._common } ) await vm.runBlock({ block, generate: true }) - postState = (await vm.eei.getStateRoot()).toString('hex') + postState = bytesToHex(await vm.eei.getStateRoot()) st.equal( postState, '23eadd91fca55c0e14034e4d63b2b3ed43f2e807b6bf4d276b784ac245e7fa3f', @@ -192,7 +191,7 @@ tape('EIP4895 tests', (t) => { }) const genesisBlock = blockchain.genesisBlock st.equal( - genesisBlock.header.stateRoot.toString('hex'), + bytesToHex(genesisBlock.header.stateRoot), 'ca3149fa9e37db08d1cd49c9061db1002ef1cd58db2210f2115c8c989b2bdf45', 'correct state root should be generated' ) @@ -200,8 +199,8 @@ tape('EIP4895 tests', (t) => { await vm.eei.generateCanonicalGenesis(parseGethGenesisState(genesisJSON)) const vmCopy = await vm.copy() - const gethBlockBufferArray = decode(Buffer.from(gethWithdrawals8BlockRlp, 'hex')) - const withdrawals = (gethBlockBufferArray[3] as WithdrawalBuffer[]).map((wa) => + const gethBlockBufferArray = decode(hexToBytes(gethWithdrawals8BlockRlp)) + const withdrawals = (gethBlockBufferArray[3] as WithdrawalBytes[]).map((wa) => Withdrawal.fromValuesArray(wa) ) const td = await blockchain.getTotalDifficulty(genesisBlock.hash()) @@ -219,7 +218,7 @@ tape('EIP4895 tests', (t) => { const block = await blockBuilder.build() st.equal( - block.header.stateRoot.toString('hex'), + bytesToHex(block.header.stateRoot), '23eadd91fca55c0e14034e4d63b2b3ed43f2e807b6bf4d276b784ac245e7fa3f', 'correct state root should be generated' ) @@ -227,9 +226,9 @@ tape('EIP4895 tests', (t) => { // block should successfully execute with VM.runBlock and have same outputs const result = await vmCopy.runBlock({ block }) st.equal(result.gasUsed, block.header.gasUsed) - st.ok(result.receiptsRoot.equals(block.header.receiptTrie)) - st.ok(result.stateRoot.equals(block.header.stateRoot)) - st.ok(result.logsBloom.equals(block.header.logsBloom)) + st.deepEquals(result.receiptsRoot, block.header.receiptTrie) + st.deepEquals(result.stateRoot, block.header.stateRoot) + st.deepEquals(result.logsBloom, block.header.logsBloom) st.end() }) }) diff --git a/packages/vm/test/api/bloom.spec.ts b/packages/vm/test/api/bloom.spec.ts index cc00e59708..32fd2a1186 100644 --- a/packages/vm/test/api/bloom.spec.ts +++ b/packages/vm/test/api/bloom.spec.ts @@ -1,4 +1,5 @@ import * as utils from '@ethereumjs/util' +import { bytesToHex, hexToBytes, utf8ToBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' import { Bloom } from '../../src/bloom' @@ -24,65 +25,56 @@ tape('bloom', (t: tape.Test) => { t.test('should contain values of hardcoded bitvector', (st) => { const hex = '00000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000' - const vector = Buffer.from(hex, 'hex') + const vector = hexToBytes(hex) const b = new Bloom(vector) - st.true(b.check(Buffer.from('value 1', 'utf8')), 'should contain string "value 1"') - st.true(b.check(Buffer.from('value 2', 'utf8')), 'should contain string "value 2"') + st.true(b.check(utf8ToBytes('value 1')), 'should contain string "value 1"') + st.true(b.check(utf8ToBytes('value 2')), 'should contain string "value 2"') st.end() }) t.test('check shouldnt be tautology', (st) => { const b = new Bloom() - st.false( - b.check(Buffer.from('random value', 'utf8')), - 'should not contain string "random value"' - ) + st.false(b.check(utf8ToBytes('random value')), 'should not contain string "random value"') st.end() }) t.test('should correctly add value', (st) => { const b = new Bloom() - b.add(Buffer.from('value', 'utf8')) - const found = b.check(Buffer.from('value', 'utf8')) + b.add(utf8ToBytes('value')) + const found = b.check(utf8ToBytes('value')) st.true(found, 'should contain added value') st.end() }) t.test('should check multiple values', (st) => { const b = new Bloom() - b.add(Buffer.from('value 1', 'utf8')) - b.add(Buffer.from('value 2', 'utf8')) - const found = b.multiCheck([Buffer.from('value 1'), Buffer.from('value 2')]) + b.add(utf8ToBytes('value 1')) + b.add(utf8ToBytes('value 2')) + const found = b.multiCheck([utf8ToBytes('value 1'), utf8ToBytes('value 2')]) st.true(found, 'should contain both values') st.end() }) t.test('should or two filters', (st) => { const b1 = new Bloom() - b1.add(Buffer.from('value 1', 'utf8')) + b1.add(utf8ToBytes('value 1')) const b2 = new Bloom() - b2.add(Buffer.from('value 2', 'utf8')) + b2.add(utf8ToBytes('value 2')) b1.or(b2) - st.true(b1.check(Buffer.from('value 2', 'utf-8')), 'should contain "value 2" after or') + st.true(b1.check(utf8ToBytes('value 2')), 'should contain "value 2" after or') st.end() }) t.test('should generate the correct bloom filter value', (st) => { const bloom = new Bloom() - bloom.add(Buffer.from('1d7022f5b17d2f8b695918fb48fa1089c9f85401', 'hex')) - bloom.add( - Buffer.from('8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925', 'hex') - ) - bloom.add( - Buffer.from('0000000000000000000000005409ed021d9299bf6814279a6a1411a7e866a631', 'hex') - ) - bloom.add( - Buffer.from('0000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c48', 'hex') - ) + bloom.add(hexToBytes('1d7022f5b17d2f8b695918fb48fa1089c9f85401')) + bloom.add(hexToBytes('8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925')) + bloom.add(hexToBytes('0000000000000000000000005409ed021d9299bf6814279a6a1411a7e866a631')) + bloom.add(hexToBytes('0000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c48')) st.equal( - bloom.bitvector.toString('hex'), + bytesToHex(bloom.bitvector), '00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000081100200000000000000000000000000000000000000000000000000000000008000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000002000000000000000004000000000000000000000' ) st.end() diff --git a/packages/vm/test/api/buildBlock.spec.ts b/packages/vm/test/api/buildBlock.spec.ts index 0c45d30fdb..aa2420a452 100644 --- a/packages/vm/test/api/buildBlock.spec.ts +++ b/packages/vm/test/api/buildBlock.spec.ts @@ -2,7 +2,8 @@ import { Block } from '@ethereumjs/block' import { Blockchain } from '@ethereumjs/blockchain' import { Chain, Common, Hardfork } from '@ethereumjs/common' import { FeeMarketEIP1559Transaction, Transaction } from '@ethereumjs/tx' -import { Account, Address } from '@ethereumjs/util' +import { Account, Address, concatBytesNoTypeCheck } from '@ethereumjs/util' +import { hexToBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' import { VM } from '../../src/vm' @@ -50,9 +51,9 @@ tape('BlockBuilder', async (t) => { } const result = await vmCopy.runBlock({ block }) st.equal(result.gasUsed, block.header.gasUsed) - st.ok(result.receiptsRoot.equals(block.header.receiptTrie)) - st.ok(result.stateRoot.equals(block.header.stateRoot)) - st.ok(result.logsBloom.equals(block.header.logsBloom)) + st.deepEquals(result.receiptsRoot, block.header.receiptTrie) + st.deepEquals(result.stateRoot, block.header.stateRoot) + st.deepEquals(result.logsBloom, block.header.logsBloom) st.end() }) @@ -112,33 +113,33 @@ tape('BlockBuilder', async (t) => { await blockBuilder.addTransaction(tx) const sealOpts = { - mixHash: Buffer.alloc(32), - nonce: Buffer.alloc(8), + mixHash: new Uint8Array(32), + nonce: new Uint8Array(8), } const block = await blockBuilder.build(sealOpts) - st.ok(block.header.mixHash.equals(sealOpts.mixHash)) - st.ok(block.header.nonce.equals(sealOpts.nonce)) + st.deepEquals(block.header.mixHash, sealOpts.mixHash) + st.deepEquals(block.header.nonce, sealOpts.nonce) st.doesNotThrow(async () => vm.blockchain.consensus.validateDifficulty(block.header)) st.end() }) t.test('should correctly seal a PoA block', async (st) => { const signer = { - address: new Address(Buffer.from('0b90087d864e82a284dca15923f3776de6bb016f', 'hex')), - privateKey: Buffer.from( - '64bf9cc30328b0e42387b3c82c614e6386259136235e20c1357bd11cdee86993', - 'hex' - ), - publicKey: Buffer.from( - '40b2ebdf4b53206d2d3d3d59e7e2f13b1ea68305aec71d5d24cefe7f24ecae886d241f9267f04702d7f693655eb7b4aa23f30dcd0c3c5f2b970aad7c8a828195', - 'hex' + address: new Address(hexToBytes('0b90087d864e82a284dca15923f3776de6bb016f')), + privateKey: hexToBytes('64bf9cc30328b0e42387b3c82c614e6386259136235e20c1357bd11cdee86993'), + publicKey: hexToBytes( + '40b2ebdf4b53206d2d3d3d59e7e2f13b1ea68305aec71d5d24cefe7f24ecae886d241f9267f04702d7f693655eb7b4aa23f30dcd0c3c5f2b970aad7c8a828195' ), } const common = new Common({ chain: Chain.Rinkeby, hardfork: Hardfork.Istanbul }) // extraData: [vanity, activeSigner, seal] - const extraData = Buffer.concat([Buffer.alloc(32), signer.address.toBuffer(), Buffer.alloc(65)]) + const extraData = concatBytesNoTypeCheck( + new Uint8Array(32), + signer.address.toBytes(), + new Uint8Array(65) + ) const cliqueSigner = signer.privateKey const genesisBlock = Block.fromBlockData( { header: { gasLimit: 50000, extraData } }, @@ -152,7 +153,7 @@ tape('BlockBuilder', async (t) => { const blockBuilder = await vm.buildBlock({ parentBlock: genesisBlock, - headerData: { difficulty: 2, extraData: Buffer.alloc(97) }, + headerData: { difficulty: 2, extraData: new Uint8Array(97) }, blockOpts: { cliqueSigner, freeze: false }, }) @@ -167,8 +168,9 @@ tape('BlockBuilder', async (t) => { const block = await blockBuilder.build() st.ok(block.header.cliqueVerifySignature([signer.address]), 'should verify signature') - st.ok( - block.header.cliqueSigner().equals(signer.address), + st.deepEquals( + block.header.cliqueSigner(), + signer.address, 'should recover the correct signer address' ) st.end() @@ -246,9 +248,9 @@ tape('BlockBuilder', async (t) => { // block should successfully execute with VM.runBlock and have same outputs const result = await vmCopy.runBlock({ block }) st.equal(result.gasUsed, block.header.gasUsed) - st.ok(result.receiptsRoot.equals(block.header.receiptTrie)) - st.ok(result.stateRoot.equals(block.header.stateRoot)) - st.ok(result.logsBloom.equals(block.header.logsBloom)) + st.deepEquals(result.receiptsRoot, block.header.receiptTrie) + st.deepEquals(result.stateRoot, block.header.stateRoot) + st.deepEquals(result.logsBloom, block.header.logsBloom) st.end() }) @@ -342,9 +344,9 @@ tape('BlockBuilder', async (t) => { } const result = await vmCopy.runBlock({ block }) st.equal(result.gasUsed, block.header.gasUsed) - st.ok(result.receiptsRoot.equals(block.header.receiptTrie)) - st.ok(result.stateRoot.equals(block.header.stateRoot)) - st.ok(result.logsBloom.equals(block.header.logsBloom)) + st.deepEquals(result.receiptsRoot, block.header.receiptTrie) + st.deepEquals(result.stateRoot, block.header.stateRoot) + st.deepEquals(result.logsBloom, block.header.logsBloom) st.end() }) }) diff --git a/packages/vm/test/api/customChain.spec.ts b/packages/vm/test/api/customChain.spec.ts index 4188003a58..f95a689a96 100644 --- a/packages/vm/test/api/customChain.spec.ts +++ b/packages/vm/test/api/customChain.spec.ts @@ -4,6 +4,7 @@ import { Common, Hardfork } from '@ethereumjs/common' import { TransactionFactory } from '@ethereumjs/tx' import { Address } from '@ethereumjs/util' import { Interface } from '@ethersproject/abi' +import { bytesToHex, hexToBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' import { VM } from '../../src/vm' @@ -57,10 +58,7 @@ const block = Block.fromBlockData( common, } ) -const privateKey = Buffer.from( - 'e331b6d69882b4cb4ea581d88e0b604039a3de5967688d3dcffdd2270c0fd109', - 'hex' -) +const privateKey = hexToBytes('e331b6d69882b4cb4ea581d88e0b604039a3de5967688d3dcffdd2270c0fd109') tape('VM initialized with custom state', (t) => { t.test('should transfer eth from already existent account', async (t) => { @@ -99,14 +97,14 @@ tape('VM initialized with custom state', (t) => { const callResult = await vm.evm.runCall({ to: Address.fromString(contractAddress), - data: Buffer.from(sigHash.slice(2), 'hex'), + data: hexToBytes(sigHash.slice(2)), caller: Address.fromPrivateKey(privateKey), }) const storage = genesisState[contractAddress][2] // Returned value should be 4, because we are trying to trigger the method `retrieve` // in the contract, which returns the variable stored in slot 0x00..00 - t.equal(callResult.execResult.returnValue.toString('hex'), storage[0][1].slice(2)) + t.equal(bytesToHex(callResult.execResult.returnValue), storage[0][1].slice(2)) t.end() }) diff --git a/packages/vm/test/api/eei.spec.ts b/packages/vm/test/api/eei.spec.ts index 2fbbc803e5..c8cb1184ed 100644 --- a/packages/vm/test/api/eei.spec.ts +++ b/packages/vm/test/api/eei.spec.ts @@ -3,6 +3,7 @@ import { Common } from '@ethereumjs/common' import { EVM } from '@ethereumjs/evm' import { DefaultStateManager as StateManager } from '@ethereumjs/statemanager' import { Account, Address } from '@ethereumjs/util' +import { hexToBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' import { VM } from '../../src' @@ -100,7 +101,7 @@ tape('EEI', (t) => { ) } - const address = new Address(Buffer.from('02E815899482f27C899fB266319dE7cc97F72E87', 'hex')) + const address = new Address(hexToBytes('02E815899482f27C899fB266319dE7cc97F72E87')) void eei.putAccount(address, Account.fromAccountData({ nonce: 5, balance: '0x123' })) const vm = await VM.create({ evm }) const accountFromEEI = await vm.eei.getAccount(address) diff --git a/packages/vm/test/api/events.spec.ts b/packages/vm/test/api/events.spec.ts index 139daab38e..831f5d8920 100644 --- a/packages/vm/test/api/events.spec.ts +++ b/packages/vm/test/api/events.spec.ts @@ -1,12 +1,12 @@ import { Block } from '@ethereumjs/block' import { FeeMarketEIP1559Transaction } from '@ethereumjs/tx' -import { Account, Address, bufferToHex, toBuffer } from '@ethereumjs/util' +import { Account, Address, bytesToPrefixedHexString, toBytes } from '@ethereumjs/util' import * as tape from 'tape' import { VM } from '../../src/vm' tape('VM events', (t) => { - const privKey = toBuffer('0xa5737ecdc1b89ca0091647e727ba082ed8953f29182e94adc397210dda643b07') + const privKey = toBytes('0xa5737ecdc1b89ca0091647e727ba082ed8953f29182e94adc397210dda643b07') t.test('should emit the Block before running it', async (st) => { const vm = await VM.create() @@ -90,7 +90,7 @@ tape('VM events', (t) => { await vm.runTx({ tx, skipBalance: true, skipHardForkValidation: true }) - st.equal(bufferToHex(emitted.execResult.returnValue), '0x') + st.equal(bytesToPrefixedHexString(emitted.execResult.returnValue), '0x') st.end() }) @@ -113,8 +113,8 @@ tape('VM events', (t) => { await vm.runTx({ tx, skipBalance: true, skipHardForkValidation: true }) - st.equal(bufferToHex(emitted.to), '0x1111111111111111111111111111111111111111') - st.equal(bufferToHex(emitted.code), '0x') + st.equal(emitted.to.toString(), '0x1111111111111111111111111111111111111111') + st.equal(bytesToPrefixedHexString(emitted.code), '0x') st.end() }) @@ -137,7 +137,7 @@ tape('VM events', (t) => { await vm.runTx({ tx, skipBalance: true, skipHardForkValidation: true }) - st.equal(bufferToHex(emitted.createdAddress), '0x') + st.equal(bytesToPrefixedHexString(emitted.createdAddress), '0x') st.end() }) @@ -186,7 +186,7 @@ tape('VM events', (t) => { await vm.runTx({ tx, skipBalance: true, skipHardForkValidation: true }) st.equal( - bufferToHex(emitted.code), + bytesToPrefixedHexString(emitted.code), '0x7f410000000000000000000000000000000000000000000000000000000000000060005260016000f3' ) diff --git a/packages/vm/test/api/index.spec.ts b/packages/vm/test/api/index.spec.ts index a4bb1c1bba..61f7b7cb72 100644 --- a/packages/vm/test/api/index.spec.ts +++ b/packages/vm/test/api/index.spec.ts @@ -3,7 +3,7 @@ import { Chain, Common, Hardfork } from '@ethereumjs/common' import { EVM } from '@ethereumjs/evm' import { Account, Address, KECCAK256_RLP } from '@ethereumjs/util' -import { Buffer } from 'buffer' +import { hexToBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' import * as util from 'util' // eslint-disable-line @typescript-eslint/no-unused-vars @@ -255,10 +255,8 @@ tape('VM -> hardforkByBlockNumber, hardforkByTTD, state (deprecated), blockchain }) tape('Ensure that precompile activation creates non-empty accounts', async (t) => { // setup the accounts for this test - const caller = new Address(Buffer.from('00000000000000000000000000000000000000ee', 'hex')) // caller address - const contractAddress = new Address( - Buffer.from('00000000000000000000000000000000000000ff', 'hex') - ) // contract address + const caller = new Address(hexToBytes('00000000000000000000000000000000000000ee')) // caller address + const contractAddress = new Address(hexToBytes('00000000000000000000000000000000000000ff')) // contract address // setup the vm const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Istanbul }) const vmNotActivated = await VM.create({ common }) @@ -279,9 +277,9 @@ tape('VM -> hardforkByBlockNumber, hardforkByTTD, state (deprecated), blockchain STOP */ - await vmNotActivated.stateManager.putContractCode(contractAddress, Buffer.from(code, 'hex')) // setup the contract code + await vmNotActivated.stateManager.putContractCode(contractAddress, hexToBytes(code)) // setup the contract code await vmNotActivated.stateManager.putAccount(caller, new Account(BigInt(0), BigInt(0x111))) // give calling account a positive balance - await vmActivated.stateManager.putContractCode(contractAddress, Buffer.from(code, 'hex')) // setup the contract code + await vmActivated.stateManager.putContractCode(contractAddress, hexToBytes(code)) // setup the contract code await vmActivated.stateManager.putAccount(caller, new Account(BigInt(0), BigInt(0x111))) // give calling account a positive balance // setup the call arguments const runCallArgs = { diff --git a/packages/vm/test/api/istanbul/eip-1108.spec.ts b/packages/vm/test/api/istanbul/eip-1108.spec.ts index 459f1a0c5c..9d235228e4 100644 --- a/packages/vm/test/api/istanbul/eip-1108.spec.ts +++ b/packages/vm/test/api/istanbul/eip-1108.spec.ts @@ -1,5 +1,6 @@ import { Chain, Common, Hardfork } from '@ethereumjs/common' import { getActivePrecompiles } from '@ethereumjs/evm' +import { hexToBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' import { VM } from '../../../src/vm' @@ -12,7 +13,7 @@ tape('Istanbul: EIP-1108 tests', (t) => { const ECADD = getActivePrecompiles(common).get(address)! const result = await ECADD({ - data: Buffer.alloc(0), + data: new Uint8Array(0), gasLimit: BigInt(0xffff), _common: common, _EVM: vm.evm, @@ -29,7 +30,7 @@ tape('Istanbul: EIP-1108 tests', (t) => { const ECMUL = getActivePrecompiles(common).get(address)! const result = await ECMUL({ - data: Buffer.alloc(0), + data: new Uint8Array(0), gasLimit: BigInt(0xffff), _common: common, _EVM: vm.evm, @@ -46,9 +47,8 @@ tape('Istanbul: EIP-1108 tests', (t) => { const ECPAIRING = getActivePrecompiles(common).get(address)! const result = await ECPAIRING({ - data: Buffer.from( - '00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa000000000000000000000000000000000000000000000000000000000000000130644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd45198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa', - 'hex' + data: hexToBytes( + '00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa000000000000000000000000000000000000000000000000000000000000000130644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd45198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa' ), gasLimit: BigInt(0xffffff), _common: common, diff --git a/packages/vm/test/api/istanbul/eip-1344.spec.ts b/packages/vm/test/api/istanbul/eip-1344.spec.ts index 817ea35154..43ce3df2ab 100644 --- a/packages/vm/test/api/istanbul/eip-1344.spec.ts +++ b/packages/vm/test/api/istanbul/eip-1344.spec.ts @@ -1,6 +1,7 @@ import { Chain, Common, Hardfork } from '@ethereumjs/common' import { ERROR } from '@ethereumjs/evm/dist/exceptions' -import { bufferToBigInt } from '@ethereumjs/util' +import { bytesToBigInt } from '@ethereumjs/util' +import { hexToBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' import { VM } from '../../../src/vm' @@ -17,7 +18,7 @@ const code = ['46', '60', '00', '53', '60', '01', '60', '00', 'f3'] tape('Istanbul: EIP-1344', async (t) => { t.test('CHAINID', async (st) => { const runCodeArgs = { - code: Buffer.from(code.join(''), 'hex'), + code: hexToBytes(code.join('')), gasLimit: BigInt(0xffff), } @@ -27,11 +28,11 @@ tape('Istanbul: EIP-1344', async (t) => { const vm = await VM.create({ common }) try { const res = await vm.evm.runCode!(runCodeArgs) - if (testCase.err) { + if (testCase.err !== undefined) { st.equal(res.exceptionError?.error, testCase.err) } else { st.assert(res.exceptionError === undefined) - st.equal(testCase.chainId, bufferToBigInt(res.returnValue)) + st.equal(testCase.chainId, bytesToBigInt(res.returnValue)) } } catch (e: any) { st.fail(e.message) diff --git a/packages/vm/test/api/istanbul/eip-152.spec.ts b/packages/vm/test/api/istanbul/eip-152.spec.ts index e568d27255..b2ed8d265b 100644 --- a/packages/vm/test/api/istanbul/eip-152.spec.ts +++ b/packages/vm/test/api/istanbul/eip-152.spec.ts @@ -1,6 +1,7 @@ import { Chain, Common, Hardfork } from '@ethereumjs/common' import { ERROR } from '@ethereumjs/evm/dist/exceptions' import { F, precompile09 } from '@ethereumjs/evm/dist/precompiles/09-blake2f' +import { bytesToHex, hexToBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' import { VM } from '../../../src/vm' @@ -91,7 +92,7 @@ tape('Istanbul: EIP-152', (t) => { for (const testCase of failingTestCases) { st.comment(testCase.name) const res = precompile09({ - data: Buffer.from(testCase.input, 'hex'), + data: hexToBytes(testCase.input), gasLimit: BigInt(20), _common: common, _EVM: vm.evm, @@ -102,12 +103,12 @@ tape('Istanbul: EIP-152', (t) => { for (const testCase of testCases) { st.comment(testCase.name) const res = precompile09({ - data: Buffer.from(testCase.input, 'hex'), + data: hexToBytes(testCase.input), gasLimit: BigInt(10000000), _common: common, _EVM: vm.evm, }) - st.equal(res.returnValue.toString('hex'), testCase.expected) + st.equal(bytesToHex(res.returnValue), testCase.expected) } st.end() diff --git a/packages/vm/test/api/istanbul/eip-1884.spec.ts b/packages/vm/test/api/istanbul/eip-1884.spec.ts index c0d2e7f296..6d27f86b55 100644 --- a/packages/vm/test/api/istanbul/eip-1884.spec.ts +++ b/packages/vm/test/api/istanbul/eip-1884.spec.ts @@ -1,6 +1,7 @@ import { Chain, Common, Hardfork } from '@ethereumjs/common' import { ERROR } from '@ethereumjs/evm/dist/exceptions' -import { Address, bufferToBigInt } from '@ethereumjs/util' +import { Address, bytesToBigInt } from '@ethereumjs/util' +import { hexToBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' import { VM } from '../../../src/vm' @@ -15,9 +16,9 @@ const testCases = [ const code = ['47', '60', '00', '53', '60', '01', '60', '00', 'f3'] tape('Istanbul: EIP-1884', async (t) => { t.test('SELFBALANCE', async (st) => { - const addr = new Address(Buffer.from('00000000000000000000000000000000000000ff', 'hex')) + const addr = new Address(hexToBytes('00000000000000000000000000000000000000ff')) const runCodeArgs = { - code: Buffer.from(code.join(''), 'hex'), + code: hexToBytes(code.join('')), gasLimit: BigInt(0xffff), address: addr, } @@ -34,11 +35,11 @@ tape('Istanbul: EIP-1884', async (t) => { try { const res = await vm.evm.runCode!(runCodeArgs) - if (testCase.err) { + if (testCase.err !== undefined) { st.equal(res.exceptionError?.error, testCase.err) } else { st.assert(res.exceptionError === undefined) - st.assert(BigInt(testCase.selfbalance) === bufferToBigInt(res.returnValue)) + st.assert(BigInt(testCase.selfbalance!) === bytesToBigInt(res.returnValue)) } } catch (e: any) { st.fail(e.message) diff --git a/packages/vm/test/api/istanbul/eip-2200.spec.ts b/packages/vm/test/api/istanbul/eip-2200.spec.ts index 3946966114..e6351a252c 100644 --- a/packages/vm/test/api/istanbul/eip-2200.spec.ts +++ b/packages/vm/test/api/istanbul/eip-2200.spec.ts @@ -1,5 +1,6 @@ import { Chain, Common, Hardfork } from '@ethereumjs/common' -import { Address, setLengthLeft, toBuffer } from '@ethereumjs/util' +import { Address, setLengthLeft, toBytes } from '@ethereumjs/util' +import { hexToBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' import { VM } from '../../../src/vm' @@ -43,9 +44,9 @@ const testCases = [ tape('Istanbul: EIP-2200', async (t) => { t.test('net-metering SSTORE', async (st) => { - const caller = new Address(Buffer.from('0000000000000000000000000000000000000000', 'hex')) - const addr = new Address(Buffer.from('00000000000000000000000000000000000000ff', 'hex')) - const key = setLengthLeft(toBuffer('0x' + BigInt(0).toString(16)), 32) + const caller = new Address(hexToBytes('0000000000000000000000000000000000000000')) + const addr = new Address(hexToBytes('00000000000000000000000000000000000000ff')) + const key = setLengthLeft(toBytes('0x' + BigInt(0).toString(16)), 32) for (const testCase of testCases) { const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Istanbul }) @@ -53,12 +54,12 @@ tape('Istanbul: EIP-2200', async (t) => { const account = createAccount(BigInt(0), BigInt(0)) await vm.stateManager.putAccount(addr, account) - await vm.stateManager.putContractCode(addr, Buffer.from(testCase.code, 'hex')) + await vm.stateManager.putContractCode(addr, hexToBytes(testCase.code)) if (testCase.original !== BigInt(0)) { await vm.stateManager.putContractStorage( addr, key, - toBuffer('0x' + testCase.original.toString(16)) + toBytes('0x' + testCase.original.toString(16)) ) } diff --git a/packages/vm/test/api/runBlock.spec.ts b/packages/vm/test/api/runBlock.spec.ts index 572380e44c..b600b015b4 100644 --- a/packages/vm/test/api/runBlock.spec.ts +++ b/packages/vm/test/api/runBlock.spec.ts @@ -7,7 +7,8 @@ import { FeeMarketEIP1559Transaction, Transaction, } from '@ethereumjs/tx' -import { Account, Address, KECCAK256_RLP, toBuffer } from '@ethereumjs/util' +import { Account, Address, KECCAK256_RLP, toBytes } from '@ethereumjs/util' +import { hexToBytes, utf8ToBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' import { VM } from '../../src/vm' @@ -30,18 +31,19 @@ const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Berlin }) tape('runBlock() -> successful API parameter usage', async (t) => { async function simpleRun(vm: VM, st: tape.Test) { const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.London }) - const genesisRlp = toBuffer(testData.genesisRLP) + const genesisRlp = toBytes(testData.genesisRLP) const genesis = Block.fromRLPSerializedBlock(genesisRlp, { common }) - const blockRlp = toBuffer(testData.blocks[0].rlp) + const blockRlp = toBytes(testData.blocks[0].rlp) const block = Block.fromRLPSerializedBlock(blockRlp, { common }) //@ts-ignore await setupPreConditions(vm.eei, testData) - st.ok( + st.deepEquals( //@ts-ignore - vm.stateManager._trie.root().equals(genesis.header.stateRoot), + vm.stateManager._trie.root(), + genesis.header.stateRoot, 'genesis state root should match calculated state root' ) @@ -67,7 +69,7 @@ tape('runBlock() -> successful API parameter usage', async (t) => { await setupPreConditions(vm.eei, testData) const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.London }) - const block1Rlp = toBuffer(testData.blocks[0].rlp) + const block1Rlp = toBytes(testData.blocks[0].rlp) const block1 = Block.fromRLPSerializedBlock(block1Rlp, { common }) await vm.runBlock({ block: block1, @@ -77,7 +79,7 @@ tape('runBlock() -> successful API parameter usage', async (t) => { skipHardForkValidation: true, }) - const block2Rlp = toBuffer(testData.blocks[1].rlp) + const block2Rlp = toBytes(testData.blocks[1].rlp) const block2 = Block.fromRLPSerializedBlock(block2Rlp, { common }) await vm.runBlock({ block: block2, @@ -87,7 +89,7 @@ tape('runBlock() -> successful API parameter usage', async (t) => { skipHardForkValidation: true, }) - const block3Rlp = toBuffer(testData.blocks[2].rlp) + const block3Rlp = toBytes(testData.blocks[2].rlp) const block3 = Block.fromRLPSerializedBlock(block3Rlp, { common }) await vm.runBlock({ block: block3, @@ -146,9 +148,8 @@ tape('runBlock() -> successful API parameter usage', async (t) => { hardfork: Hardfork.Chainstart, }) - const privateKey = Buffer.from( - 'e331b6d69882b4cb4ea581d88e0b604039a3de5967688d3dcffdd2270c0fd109', - 'hex' + const privateKey = hexToBytes( + 'e331b6d69882b4cb4ea581d88e0b604039a3de5967688d3dcffdd2270c0fd109' ) function getBlock(common: Common): Block { @@ -202,7 +203,7 @@ tape('runBlock() -> API parameter usage/data errors', async (t) => { t.test('should fail when runTx fails', async (t) => { const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.London }) - const blockRlp = toBuffer(testData.blocks[0].rlp) + const blockRlp = toBytes(testData.blocks[0].rlp) const block = Block.fromRLPSerializedBlock(blockRlp, { common }) // The mocked VM uses a mocked runTx @@ -219,7 +220,7 @@ tape('runBlock() -> API parameter usage/data errors', async (t) => { const block = Block.fromBlockData({ header: { ...testData.blocks[0].header, - gasLimit: Buffer.from('8000000000000000', 'hex'), + gasLimit: hexToBytes('8000000000000000'), }, }) await vm @@ -231,7 +232,7 @@ tape('runBlock() -> API parameter usage/data errors', async (t) => { t.test('should fail when block validation fails', async (t) => { const vm = await VM.create({ common }) - const blockRlp = toBuffer(testData.blocks[0].rlp) + const blockRlp = toBytes(testData.blocks[0].rlp) const block = Object.create(Block.fromRLPSerializedBlock(blockRlp, { common })) await vm @@ -244,7 +245,7 @@ tape('runBlock() -> API parameter usage/data errors', async (t) => { t.test('should fail when no `validateHeader` method exists on blockchain class', async (t) => { const vm = await VM.create({ common }) - const blockRlp = toBuffer(testData.blocks[0].rlp) + const blockRlp = toBytes(testData.blocks[0].rlp) const block = Object.create(Block.fromRLPSerializedBlock(blockRlp, { common })) ;(vm.blockchain as any).validateHeader = undefined try { @@ -261,7 +262,7 @@ tape('runBlock() -> API parameter usage/data errors', async (t) => { t.test('should fail when tx gas limit higher than block gas limit', async (t) => { const vm = await VM.create({ common }) - const blockRlp = toBuffer(testData.blocks[0].rlp) + const blockRlp = toBytes(testData.blocks[0].rlp) const block = Object.create(Block.fromRLPSerializedBlock(blockRlp, { common })) // modify first tx's gasLimit const { nonce, gasPrice, to, value, data, v, r, s } = block.transactions[0] @@ -289,7 +290,7 @@ tape('runBlock() -> runtime behavior', async (t) => { const block1: any = RLP.decode(testData.blocks[0].rlp) // edit extra data of this block to "dao-hard-fork" - block1[0][12] = Buffer.from('dao-hard-fork') + block1[0][12] = utf8ToBytes('dao-hard-fork') const block = Block.fromValuesArray(block1, { common }) // @ts-ignore await setupPreConditions(vm.eei, testData) @@ -298,20 +299,18 @@ tape('runBlock() -> runtime behavior', async (t) => { const fundBalance1 = BigInt('0x1111') const accountFunded1 = createAccount(BigInt(0), fundBalance1) const DAOFundedContractAddress1 = new Address( - Buffer.from('d4fe7bc31cedb7bfb8a345f31e668033056b2728', 'hex') + hexToBytes('d4fe7bc31cedb7bfb8a345f31e668033056b2728') ) await vm.stateManager.putAccount(DAOFundedContractAddress1, accountFunded1) const fundBalance2 = BigInt('0x2222') const accountFunded2 = createAccount(BigInt(0), fundBalance2) const DAOFundedContractAddress2 = new Address( - Buffer.from('b3fb0e5aba0e20e5c49d252dfd30e102b171a425', 'hex') + hexToBytes('b3fb0e5aba0e20e5c49d252dfd30e102b171a425') ) await vm.stateManager.putAccount(DAOFundedContractAddress2, accountFunded2) - const DAORefundAddress = new Address( - Buffer.from('bf4ed7b27f1d666546e30d74d50d173d20bca754', 'hex') - ) + const DAORefundAddress = new Address(hexToBytes('bf4ed7b27f1d666546e30d74d50d173d20bca754')) const fundBalanceRefund = BigInt('0x4444') const accountRefund = createAccount(BigInt(0), fundBalanceRefund) await vm.stateManager.putAccount(DAORefundAddress, accountRefund) @@ -339,26 +338,18 @@ tape('runBlock() -> runtime behavior', async (t) => { const vm = await setupVM({ common }) const signer = { - address: new Address(Buffer.from('0b90087d864e82a284dca15923f3776de6bb016f', 'hex')), - privateKey: Buffer.from( - '64bf9cc30328b0e42387b3c82c614e6386259136235e20c1357bd11cdee86993', - 'hex' - ), - publicKey: Buffer.from( - '40b2ebdf4b53206d2d3d3d59e7e2f13b1ea68305aec71d5d24cefe7f24ecae886d241f9267f04702d7f693655eb7b4aa23f30dcd0c3c5f2b970aad7c8a828195', - 'hex' + address: new Address(hexToBytes('0b90087d864e82a284dca15923f3776de6bb016f')), + privateKey: hexToBytes('64bf9cc30328b0e42387b3c82c614e6386259136235e20c1357bd11cdee86993'), + publicKey: hexToBytes( + '40b2ebdf4b53206d2d3d3d59e7e2f13b1ea68305aec71d5d24cefe7f24ecae886d241f9267f04702d7f693655eb7b4aa23f30dcd0c3c5f2b970aad7c8a828195' ), } const otherUser = { - address: new Address(Buffer.from('6f62d8382bf2587361db73ceca28be91b2acb6df', 'hex')), - privateKey: Buffer.from( - '2a6e9ad5a6a8e4f17149b8bc7128bf090566a11dbd63c30e5a0ee9f161309cd6', - 'hex' - ), - publicKey: Buffer.from( - 'ca0a55f6e81cb897aee6a1c390aa83435c41048faa0564b226cfc9f3df48b73e846377fb0fd606df073addc7bd851f22547afbbdd5c3b028c91399df802083a2', - 'hex' + address: new Address(hexToBytes('6f62d8382bf2587361db73ceca28be91b2acb6df')), + privateKey: hexToBytes('2a6e9ad5a6a8e4f17149b8bc7128bf090566a11dbd63c30e5a0ee9f161309cd6'), + publicKey: hexToBytes( + 'ca0a55f6e81cb897aee6a1c390aa83435c41048faa0564b226cfc9f3df48b73e846377fb0fd606df073addc7bd851f22547afbbdd5c3b028c91399df802083a2' ), } @@ -371,7 +362,7 @@ tape('runBlock() -> runtime behavior', async (t) => { // create block with the signer and txs const block = Block.fromBlockData( - { header: { extraData: Buffer.alloc(97) }, transactions: [tx, tx] }, + { header: { extraData: new Uint8Array(97) }, transactions: [tx, tx] }, { common, cliqueSigner: signer.privateKey } ) @@ -409,9 +400,9 @@ tape('should correctly reflect generated fields', async (t) => { // filled with 0s and no txs. Once we run it we should // get a receipt trie root of for the empty receipts set, // which is a well known constant. - const buffer32Zeros = Buffer.alloc(32, 0) + const bytes32Zeros = new Uint8Array(32) const block = Block.fromBlockData({ - header: { receiptTrie: buffer32Zeros, transactionsTrie: buffer32Zeros, gasUsed: BigInt(1) }, + header: { receiptTrie: bytes32Zeros, transactionsTrie: bytes32Zeros, gasUsed: BigInt(1) }, }) const results = await runBlockAndGetAfterBlockEvent(vm, { @@ -420,8 +411,8 @@ tape('should correctly reflect generated fields', async (t) => { skipBlockValidation: true, }) - t.ok(results.block.header.receiptTrie.equals(KECCAK256_RLP)) - t.ok(results.block.header.transactionsTrie.equals(KECCAK256_RLP)) + t.deepEquals(results.block.header.receiptTrie, KECCAK256_RLP) + t.deepEquals(results.block.header.transactionsTrie, KECCAK256_RLP) t.equal(results.block.header.gasUsed, BigInt(0)) }) @@ -429,7 +420,7 @@ async function runWithHf(hardfork: string) { const common = new Common({ chain: Chain.Mainnet, hardfork }) const vm = await setupVM({ common }) - const blockRlp = toBuffer(testData.blocks[0].rlp) + const blockRlp = toBytes(testData.blocks[0].rlp) const block = Block.fromRLPSerializedBlock(blockRlp, { common }) // @ts-ignore @@ -456,7 +447,7 @@ tape('runBlock() -> API return values', async (t) => { res = await runWithHf('spuriousDragon') t.deepEqual( (res.receipts[0] as PreByzantiumTxReceipt).stateRoot, - Buffer.from('4477e2cfaf9fd2eed4f74426798b55d140f6a9612da33413c4745f57d7a97fcc', 'hex'), + hexToBytes('4477e2cfaf9fd2eed4f74426798b55d140f6a9612da33413c4745f57d7a97fcc'), 'should return correct pre-Byzantium receipt format' ) }) @@ -466,7 +457,7 @@ tape('runBlock() -> tx types', async (t) => { async function simpleRun(vm: VM, transactions: TypedTransaction[], st: tape.Test) { const common = vm._common - const blockRlp = toBuffer(testData.blocks[0].rlp) + const blockRlp = toBytes(testData.blocks[0].rlp) const block = Block.fromRLPSerializedBlock(blockRlp, { common, freeze: false }) //@ts-ignore overwrite transactions diff --git a/packages/vm/test/api/runTx.spec.ts b/packages/vm/test/api/runTx.spec.ts index 9c7c76e4b9..0276dc48d9 100644 --- a/packages/vm/test/api/runTx.spec.ts +++ b/packages/vm/test/api/runTx.spec.ts @@ -8,6 +8,7 @@ import { TransactionFactory, } from '@ethereumjs/tx' import { Account, Address, KECCAK256_NULL, MAX_INTEGER } from '@ethereumjs/util' +import { hexToBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' import { VM } from '../../src/vm' @@ -46,7 +47,7 @@ tape('runTx() -> successful API parameter usage', async (t) => { if (vm._common.consensusType() === 'poa') { // Setup block with correct extraData for POA block = Block.fromBlockData( - { header: { extraData: Buffer.alloc(97) } }, + { header: { extraData: new Uint8Array(97) } }, { common: vm._common } ) } @@ -201,9 +202,8 @@ tape('runTx() -> successful API parameter usage', async (t) => { for (const txType of TRANSACTION_TYPES) { const vm = await VM.create({ common }) - const privateKey = Buffer.from( - 'e331b6d69882b4cb4ea581d88e0b604039a3de5967688d3dcffdd2270c0fd109', - 'hex' + const privateKey = hexToBytes( + 'e331b6d69882b4cb4ea581d88e0b604039a3de5967688d3dcffdd2270c0fd109' ) const address = Address.fromPrivateKey(privateKey) const initialBalance = BigInt(10) ** BigInt(18) @@ -229,7 +229,7 @@ tape('runTx() -> successful API parameter usage', async (t) => { ) const tx = unsignedTx.sign(privateKey) - const coinbase = Buffer.from('00000000000000000000000000000000000000ff', 'hex') + const coinbase = hexToBytes('00000000000000000000000000000000000000ff') const block = Block.fromBlockData( { header: { @@ -436,9 +436,8 @@ tape('runTx() -> runtime behavior', async (t) => { for (const txType of TRANSACTION_TYPES) { const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Berlin }) const vm = await VM.create({ common }) - const privateKey = Buffer.from( - 'e331b6d69882b4cb4ea581d88e0b604039a3de5967688d3dcffdd2270c0fd109', - 'hex' + const privateKey = hexToBytes( + 'e331b6d69882b4cb4ea581d88e0b604039a3de5967688d3dcffdd2270c0fd109' ) /* Code which is deployed here: PUSH1 01 @@ -446,13 +445,13 @@ tape('runTx() -> runtime behavior', async (t) => { SSTORE INVALID */ - const code = Buffer.from('6001600055FE', 'hex') - const address = new Address(Buffer.from('00000000000000000000000000000000000000ff', 'hex')) + const code = hexToBytes('6001600055FE') + const address = new Address(hexToBytes('00000000000000000000000000000000000000ff')) await vm.eei.putContractCode(address, code) await vm.eei.putContractStorage( address, - Buffer.from('00'.repeat(32), 'hex'), - Buffer.from('00'.repeat(31) + '01', 'hex') + hexToBytes('00'.repeat(32)), + hexToBytes('00'.repeat(31) + '01') ) const txParams: any = { nonce: '0x00', @@ -515,9 +514,7 @@ tape('runTx() -> runtime errors', async (t) => { const from = createAccount() await vm.eei.putAccount(caller, from) - const contractAddress = new Address( - Buffer.from('61de9dc6f6cff1df2809480882cfd3c2364b28f7', 'hex') - ) + const contractAddress = new Address(hexToBytes('61de9dc6f6cff1df2809480882cfd3c2364b28f7')) const to = createAccount(BigInt(0), MAX_INTEGER) await vm.eei.putAccount(contractAddress, to) @@ -558,8 +555,8 @@ tape('runTx() -> API return values', async (t) => { ) t.deepEqual( res.execResult.returnValue, - Buffer.from([]), - `execution result -> return value -> empty Buffer (${txType.name})` + Uint8Array.from([]), + `execution result -> return value -> empty Uint8Array (${txType.name})` ) t.equal(res.gasRefund, BigInt(0), `gasRefund -> 0 (${txType.name})`) } @@ -604,7 +601,7 @@ tape('runTx() -> API return values', async (t) => { t.deepEqual( res.bloom.bitvector, - Buffer.from('00'.repeat(256), 'hex'), + hexToBytes('00'.repeat(256)), `runTx result -> bloom.bitvector -> should be empty (${txType.name})` ) t.equal( @@ -673,7 +670,7 @@ tape('runTx() -> consensus bugs', async (t) => { REVERT puts an "error message" in the RETURNDATA buffer. This buffer would contain the contract code to deploy if the message would not fail. In this case, REVERT puts a message in the RETURNDATA buffer which is larger than the `maxCodeSize` This should not consume all gas: it should only consume the gas spent by the attempt to create the contract */ - const pkey = Buffer.alloc(32, 1) + const pkey = new Uint8Array(32).fill(1) const txData: FeeMarketEIP1559TxData = { gasLimit: 100000, maxPriorityFeePerGas: 1000, @@ -743,10 +740,7 @@ tape('runTx() -> skipBalance behavior', async (t) => { t.plan(6) const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Berlin }) const vm = await VM.create({ common }) - const senderKey = Buffer.from( - 'e331b6d69882b4cb4ea581d88e0b604039a3de5967688d3dcffdd2270c0fd109', - 'hex' - ) + const senderKey = hexToBytes('e331b6d69882b4cb4ea581d88e0b604039a3de5967688d3dcffdd2270c0fd109') const sender = Address.fromPrivateKey(senderKey) for (const balance of [undefined, BigInt(5)]) { @@ -777,11 +771,11 @@ tape( const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Berlin }) const vm = await VM.create({ common }) - const pkey = Buffer.alloc(32, 1) + const pkey = new Uint8Array(32).fill(1) // CALLER EXTCODEHASH PUSH 0 SSTORE STOP // Puts EXTCODEHASH of CALLER into slot 0 - const code = Buffer.from('333F60005500', 'hex') + const code = hexToBytes('333F60005500') const codeAddr = Address.fromString('0x' + '20'.repeat(20)) await vm.stateManager.putContractCode(codeAddr, code) @@ -797,11 +791,8 @@ tape( await vm.eei.putAccount(addr, acc) await vm.runTx({ tx, skipHardForkValidation: true }) - const hash = await vm.stateManager.getContractStorage( - codeAddr, - Buffer.from('00'.repeat(32), 'hex') - ) - t.ok(hash.equals(KECCAK256_NULL), 'hash ok') + const hash = await vm.stateManager.getContractStorage(codeAddr, hexToBytes('00'.repeat(32))) + t.deepEquals(hash, KECCAK256_NULL, 'hash ok') t.end() } @@ -813,7 +804,7 @@ tape( const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Berlin }) const vm = await VM.create({ common }) - const pkey = Buffer.alloc(32, 1) + const pkey = new Uint8Array(32).fill(1) // PUSH 0 DUP DUP DUP // CALLVALUE CALLER GAS @@ -821,7 +812,7 @@ tape( // STOP // Calls CALLER and sends back the ETH just sent with the transaction - const code = Buffer.from('600080808034335AF100', 'hex') + const code = hexToBytes('600080808034335AF100') const codeAddr = Address.fromString('0x' + '20'.repeat(20)) await vm.stateManager.putContractCode(codeAddr, code) @@ -852,11 +843,11 @@ tape( const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Berlin }) const vm = await VM.create({ common }) - const pkey = Buffer.alloc(32, 1) + const pkey = new Uint8Array(32).fill(1) // CALLER EXTCODEHASH PUSH 0 SSTORE STOP // Puts EXTCODEHASH of CALLER into slot 0 - const code = Buffer.from('33FF', 'hex') + const code = hexToBytes('33FF') const codeAddr = Address.fromString('0x' + '20'.repeat(20)) await vm.stateManager.putContractCode(codeAddr, code) diff --git a/packages/vm/test/api/state/accountExists.spec.ts b/packages/vm/test/api/state/accountExists.spec.ts index c9877259c4..9cfa94447a 100644 --- a/packages/vm/test/api/state/accountExists.spec.ts +++ b/packages/vm/test/api/state/accountExists.spec.ts @@ -1,5 +1,6 @@ import { Chain, Common, Hardfork } from '@ethereumjs/common' -import { Address, toBuffer } from '@ethereumjs/util' +import { Address, toBytes } from '@ethereumjs/util' +import { hexToBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' import { VM } from '../../../src/vm' @@ -10,10 +11,8 @@ tape('correctly apply new account gas fee on pre-Spurious Dragon hardforks', asy // This test verifies that issue is now resolved // setup the accounts for this test - const caller = new Address(Buffer.from('1747de68ae74afa4e00f8ef79b9c875a339cda70', 'hex')) // caller address - const contractAddress = new Address( - Buffer.from('02E815899482f27C899fB266319dE7cc97F72E87', 'hex') - ) // contract address + const caller = new Address(hexToBytes('1747de68ae74afa4e00f8ef79b9c875a339cda70')) // caller address + const contractAddress = new Address(hexToBytes('02E815899482f27C899fB266319dE7cc97F72E87')) // contract address // setup the vm const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Homestead }) const vm = await VM.create({ common }) @@ -24,19 +23,18 @@ tape('correctly apply new account gas fee on pre-Spurious Dragon hardforks', asy const existingAccount = await vm.stateManager.getAccount(existingAddress) existingAccount.balance = BigInt(1) await vm.stateManager.putAccount(existingAddress, existingAccount) - await vm.stateManager.putContractCode(contractAddress, Buffer.from(code, 'hex')) // setup the contract code + await vm.stateManager.putContractCode(contractAddress, hexToBytes(code)) // setup the contract code await vm.stateManager.putContractStorage( contractAddress, - Buffer.from('d08f588b94e47566eea77acec87441cecca23f61aea9ed8eb086c062d3837605', 'hex'), - Buffer.from('0000000000000000000000000000000000000000000000000000000000000001', 'hex') + hexToBytes('d08f588b94e47566eea77acec87441cecca23f61aea9ed8eb086c062d3837605'), + hexToBytes('0000000000000000000000000000000000000000000000000000000000000001') ) // setup the call arguments const runCallArgs = { caller, // call address gasLimit: BigInt(174146 - 22872), // tx gas limit minus the tx fee (21000) and data fee (1872) to represent correct gas costs - data: Buffer.from( - 'a9059cbb000000000000000000000000f48a1bdc65d9ccb4b569ffd4bffff415b90783d60000000000000000000000000000000000000000000000000000000000000001', - 'hex' + data: hexToBytes( + 'a9059cbb000000000000000000000000f48a1bdc65d9ccb4b569ffd4bffff415b90783d60000000000000000000000000000000000000000000000000000000000000001' ), to: contractAddress, // call to the contract address value: BigInt(0), @@ -55,10 +53,8 @@ tape( 'do not apply new account gas fee for empty account in DB on pre-Spurious Dragon hardforks', async (t) => { // setup the accounts for this test - const caller = new Address(Buffer.from('1747de68ae74afa4e00f8ef79b9c875a339cda70', 'hex')) // caller address - const contractAddress = new Address( - Buffer.from('02E815899482f27C899fB266319dE7cc97F72E87', 'hex') - ) // contract address + const caller = new Address(hexToBytes('1747de68ae74afa4e00f8ef79b9c875a339cda70')) // caller address + const contractAddress = new Address(hexToBytes('02E815899482f27C899fB266319dE7cc97F72E87')) // contract address // setup the vm const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Homestead }) const vm = await VM.create({ common }) @@ -69,23 +65,22 @@ tape( existingAccount.balance = BigInt(1) await vm.stateManager.putAccount(existingAddress, existingAccount) // add empty account to DB - const emptyAddress = new Address(Buffer.from('f48a1bdc65d9ccb4b569ffd4bffff415b90783d6', 'hex')) + const emptyAddress = new Address(hexToBytes('f48a1bdc65d9ccb4b569ffd4bffff415b90783d6')) const emptyAccount = await vm.stateManager.getAccount(emptyAddress) //@ts-ignore - vm.stateManager._trie.put(toBuffer(emptyAddress), emptyAccount.serialize()) - await vm.stateManager.putContractCode(contractAddress, Buffer.from(code, 'hex')) // setup the contract code + vm.stateManager._trie.put(toBytes(emptyAddress), emptyAccount.serialize()) + await vm.stateManager.putContractCode(contractAddress, hexToBytes(code)) // setup the contract code await vm.stateManager.putContractStorage( contractAddress, - Buffer.from('d08f588b94e47566eea77acec87441cecca23f61aea9ed8eb086c062d3837605', 'hex'), - Buffer.from('0000000000000000000000000000000000000000000000000000000000000001', 'hex') + hexToBytes('d08f588b94e47566eea77acec87441cecca23f61aea9ed8eb086c062d3837605'), + hexToBytes('0000000000000000000000000000000000000000000000000000000000000001') ) // setup the call arguments const runCallArgs = { caller, // call address gasLimit: BigInt(174146 - 22872), // tx gas limit minus the tx fee (21000) and data fee (1872) to represent correct gas costs - data: Buffer.from( - 'a9059cbb000000000000000000000000f48a1bdc65d9ccb4b569ffd4bffff415b90783d60000000000000000000000000000000000000000000000000000000000000001', - 'hex' + data: hexToBytes( + 'a9059cbb000000000000000000000000f48a1bdc65d9ccb4b569ffd4bffff415b90783d60000000000000000000000000000000000000000000000000000000000000001' ), to: contractAddress, // call to the contract address value: BigInt(0), diff --git a/packages/vm/test/api/utils.ts b/packages/vm/test/api/utils.ts index 843793beda..d6abd21eac 100644 --- a/packages/vm/test/api/utils.ts +++ b/packages/vm/test/api/utils.ts @@ -1,6 +1,7 @@ import { Blockchain } from '@ethereumjs/blockchain' import { TransactionFactory } from '@ethereumjs/tx' import { Account } from '@ethereumjs/util' +import { hexToBytes } from 'ethereum-cryptography/utils' import { MemoryLevel } from 'memory-level' import { VM } from '../../src/vm' @@ -24,7 +25,7 @@ export async function setBalance(vm: VM, address: Address, balance = BigInt(1000 export async function setupVM(opts: VMOpts & { genesisBlock?: Block } = {}) { const db: any = new MemoryLevel() const { common, genesisBlock } = opts - if (!opts.blockchain) { + if (opts.blockchain === undefined) { opts.blockchain = await Blockchain.create({ db, validateBlocks: false, @@ -98,9 +99,8 @@ export function getTransaction( const tx = TransactionFactory.fromTxData(txParams, { common, freeze: false }) if (sign) { - const privateKey = Buffer.from( - 'e331b6d69882b4cb4ea581d88e0b604039a3de5967688d3dcffdd2270c0fd109', - 'hex' + const privateKey = hexToBytes( + 'e331b6d69882b4cb4ea581d88e0b604039a3de5967688d3dcffdd2270c0fd109' ) return tx.sign(privateKey) } diff --git a/packages/vm/test/api/vmState.spec.ts b/packages/vm/test/api/vmState.spec.ts index 2396e77c67..2ff115ede9 100644 --- a/packages/vm/test/api/vmState.spec.ts +++ b/packages/vm/test/api/vmState.spec.ts @@ -2,6 +2,7 @@ import { Blockchain } from '@ethereumjs/blockchain' import { Chain, Common, Hardfork } from '@ethereumjs/common' import { DefaultStateManager } from '@ethereumjs/statemanager' import { Address } from '@ethereumjs/util' +import { hexToBytes, utf8ToBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' import { VmState } from '../../src/eei/vmState' @@ -26,7 +27,7 @@ tape('vmState', (t) => { await vmState.generateCanonicalGenesis(blockchain.genesisState()) const stateRoot = await vmState.getStateRoot() st.equal( - stateRoot.toString('hex'), + bytesToHex(stateRoot), genesisData.genesis_state_root, 'generateCanonicalGenesis should produce correct state root for mainnet from ethereum/tests data' ) @@ -40,9 +41,8 @@ tape('vmState', (t) => { return st.end() } const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Petersburg }) - const expectedStateRoot = Buffer.from( - 'd7f8974fb5ac78d9ac099b9ad5018bedc2ce0a72dad1827a1709da30580f0544', - 'hex' + const expectedStateRoot = hexToBytes( + 'd7f8974fb5ac78d9ac099b9ad5018bedc2ce0a72dad1827a1709da30580f0544' ) const stateManager = new StateManager({}) @@ -51,30 +51,31 @@ tape('vmState', (t) => { await vmState.generateCanonicalGenesis(blockchain.genesisState()) const stateRoot = await vmState.getStateRoot() - st.true( - stateRoot.equals(expectedStateRoot), + st.deepEquals( + stateRoot, + expectedStateRoot, `generateCanonicalGenesis should produce correct state root for mainnet from common` ) st.end() }) t.test('should generate the genesis state root correctly for all other chains', async (st) => { - const chains: [Chain, Buffer][] = [ + const chains: [Chain, Uint8Array][] = [ [ Chain.Ropsten, - Buffer.from('217b0bbcfb72e2d57e28f33cb361b9983513177755dc3f33ce3e7022ed62b77b', 'hex'), + hexToBytes('217b0bbcfb72e2d57e28f33cb361b9983513177755dc3f33ce3e7022ed62b77b'), ], [ Chain.Rinkeby, - Buffer.from('53580584816f617295ea26c0e17641e0120cab2f0a8ffb53a866fd53aa8e8c2d', 'hex'), + hexToBytes('53580584816f617295ea26c0e17641e0120cab2f0a8ffb53a866fd53aa8e8c2d'), ], [ Chain.Goerli, - Buffer.from('5d6cded585e73c4e322c30c2f782a336316f17dd85a4863b9d838d2d4b8b3008', 'hex'), + hexToBytes('5d6cded585e73c4e322c30c2f782a336316f17dd85a4863b9d838d2d4b8b3008'), ], [ Chain.Sepolia, - Buffer.from('5eb6e371a698b8d68f665192350ffcecbbbf322916f4b51bd79bb6887da3f494', 'hex'), + hexToBytes('5eb6e371a698b8d68f665192350ffcecbbbf322916f4b51bd79bb6887da3f494'), ], ] @@ -87,8 +88,9 @@ tape('vmState', (t) => { await vmState.generateCanonicalGenesis(blockchain.genesisState()) const stateRoot = await vmState.getStateRoot() - st.true( - stateRoot.equals(expectedStateRoot), + st.deepEquals( + stateRoot, + expectedStateRoot, `generateCanonicalGenesis should produce correct state root for ${Chain[chain]}` ) } @@ -100,20 +102,20 @@ tape('Original storage cache', async (t) => { const stateManager = new DefaultStateManager() const vmState = new VmState({ stateManager }) - const address = new Address(Buffer.from('a94f5374fce5edbc8e2a8697c15331677e6ebf0b', 'hex')) + const address = new Address(hexToBytes('a94f5374fce5edbc8e2a8697c15331677e6ebf0b')) const account = createAccount() await vmState.putAccount(address, account) - const key = Buffer.from('1234567890123456789012345678901234567890123456789012345678901234', 'hex') - const value = Buffer.from('1234', 'hex') + const key = hexToBytes('1234567890123456789012345678901234567890123456789012345678901234') + const value = hexToBytes('1234') t.test('should initially have empty storage value', async (st) => { await vmState.checkpoint() const res = await vmState.getContractStorage(address, key) - st.deepEqual(res, Buffer.alloc(0)) + st.deepEqual(res, new Uint8Array(0)) const origRes = await (vmState).getOriginalContractStorage(address, key) - st.deepEqual(origRes, Buffer.alloc(0)) + st.deepEqual(origRes, new Uint8Array(0)) await vmState.commit() @@ -135,7 +137,7 @@ tape('Original storage cache', async (t) => { }) t.test('should return correct original value after modification', async (st) => { - const newValue = Buffer.from('1235', 'hex') + const newValue = hexToBytes('1235') await vmState.putContractStorage(address, key, newValue) const res = await vmState.getContractStorage(address, key) st.deepEqual(res, newValue) @@ -146,12 +148,9 @@ tape('Original storage cache', async (t) => { }) t.test('should cache keys separately', async (st) => { - const key2 = Buffer.from( - '0000000000000000000000000000000000000000000000000000000000000012', - 'hex' - ) - const value2 = Buffer.from('12', 'hex') - const value3 = Buffer.from('123', 'hex') + const key2 = hexToBytes('0000000000000000000000000000000000000000000000000000000000000012') + const value2 = utf8ToBytes('12') + const value3 = utf8ToBytes('123') await vmState.putContractStorage(address, key2, value2) let res = await vmState.getContractStorage(address, key2) @@ -168,7 +167,7 @@ tape('Original storage cache', async (t) => { // Check previous key res = await vmState.getContractStorage(address, key) - st.deepEqual(res, Buffer.from('1235', 'hex')) + st.deepEqual(res, hexToBytes('1235')) origRes = await (vmState).getOriginalContractStorage(address, key) st.deepEqual(origRes, value) @@ -177,7 +176,7 @@ tape('Original storage cache', async (t) => { t.test("getOriginalContractStorage should validate the key's length", async (st) => { try { - await (vmState).getOriginalContractStorage(address, Buffer.alloc(12)) + await (vmState).getOriginalContractStorage(address, new Uint8Array(12)) } catch (e: any) { st.equal(e.message, 'Storage key must be 32 bytes long') st.end() @@ -194,12 +193,12 @@ tape('StateManager - generateAccessList', (tester) => { // Only use 0..9 function a(n: number) { - return Buffer.from(`ff${'00'.repeat(18)}0${n}`, 'hex') + return hexToBytes(`ff${'00'.repeat(18)}0${n}`) } // Only use 0..9 function s(n: number) { - return Buffer.from(`${'00'.repeat(31)}0${n}`, 'hex') + return hexToBytes(`${'00'.repeat(31)}0${n}`) } function getStateManagerAliases() { diff --git a/packages/vm/test/retesteth/transition-child.ts b/packages/vm/test/retesteth/transition-child.ts index 4d586a84a4..694920e0f7 100644 --- a/packages/vm/test/retesteth/transition-child.ts +++ b/packages/vm/test/retesteth/transition-child.ts @@ -2,8 +2,9 @@ import { Block, BlockHeader } from '@ethereumjs/block' import { Blockchain } from '@ethereumjs/blockchain' import { RLP } from '@ethereumjs/rlp' import { Transaction, TransactionFactory } from '@ethereumjs/tx' -import { arrToBufArr } from '@ethereumjs/util' +import { bytesToPrefixedHexString } from '@ethereumjs/util' import { keccak256 } from 'ethereum-cryptography/keccak' +import { hexToBytes } from 'ethereum-cryptography/utils' import { readFileSync, writeFileSync } from 'fs' import { join } from 'path' @@ -14,7 +15,7 @@ import { makeBlockFromEnv, setupPreConditions } from '../util' import type { PostByzantiumTxReceipt } from '../../src' import type { TypedTransaction } from '@ethereumjs/tx' -import type { NestedBufferArray } from '@ethereumjs/util' +import type { NestedUint8Array } from '@ethereumjs/util' const yargs = require('yargs/yargs') @@ -58,7 +59,8 @@ async function runTransition(argsIn: any) { const genesis = Block.fromBlockData({ header: BlockHeader.fromHeaderData(genesisBlockData) }) blockchain = await Blockchain.create({ common, genesisBlock: genesis }) } - const vm = blockchain ? await VM.create({ common, blockchain }) : await VM.create({ common }) + const vm = + blockchain !== undefined ? await VM.create({ common, blockchain }) : await VM.create({ common }) await setupPreConditions(vm.eei, { pre: alloc }) const block = makeBlockFromEnv(inputEnv, { common }) @@ -66,7 +68,7 @@ async function runTransition(argsIn: any) { const acc = await vm.stateManager.getAccount(block.header.coinbase) await vm.stateManager.putAccount(block.header.coinbase, acc) - const txsData = arrToBufArr(RLP.decode(Buffer.from(rlpTxs.slice(2), 'hex'))) + const txsData = RLP.decode(hexToBytes(rlpTxs.slice(2))) const headerData = block.header.toJSON() headerData.difficulty = inputEnv.parentDifficulty @@ -87,9 +89,9 @@ async function runTransition(argsIn: any) { root: '0x', status: receipt.status === 0 ? '0x' : '0x1', cumulativeGasUsed: '0x' + receipt.cumulativeBlockGasUsed.toString(16), - logsBloom: '0x' + receipt.bitvector.toString('hex'), + logsBloom: bytesToPrefixedHexString(receipt.bitvector), logs: null, - transactionHash: '0x' + afterTx.transaction.hash().toString('hex'), + transactionHash: bytesToPrefixedHexString(afterTx.transaction.hash()), contractAddress: '0x0000000000000000000000000000000000000000', gasUsed: '0x' + afterTx.totalGasSpent.toString(16), blockHash: '0x0000000000000000000000000000000000000000000000000000000000000000', @@ -103,13 +105,13 @@ async function runTransition(argsIn: any) { const rejected = [] let index = 0 - for (const txData of txsData) { + for (const txData of txsData) { try { let tx: TypedTransaction - if (Buffer.isBuffer(txData)) { - tx = TransactionFactory.fromSerializedData(txData as Buffer, { common }) + if (txData instanceof Uint8Array) { + tx = TransactionFactory.fromSerializedData(txData as Uint8Array, { common }) } else { - tx = Transaction.fromValuesArray(txData as Buffer[], { common }) + tx = Transaction.fromValuesArray(txData as Uint8Array[], { common }) } await builder.addTransaction(tx) } catch (e: any) { @@ -122,16 +124,16 @@ async function runTransition(argsIn: any) { } const logsBloom = builder.logsBloom() - const logsHash = Buffer.from(keccak256(logsBloom)) + const logsHash = keccak256(logsBloom) await vm.eei.cleanupTouchedAccounts() const output = { - stateRoot: '0x' + (await vm.eei.getStateRoot()).toString('hex'), - txRoot: '0x' + (await builder.transactionsTrie()).toString('hex'), - receiptsRoot: '0x' + (await builder.receiptTrie()).toString('hex'), - logsHash: '0x' + logsHash.toString('hex'), - logsBloom: '0x' + logsBloom.toString('hex'), + stateRoot: bytesToPrefixedHexString(await vm.eei.getStateRoot()), + txRoot: bytesToPrefixedHexString(await builder.transactionsTrie()), + receiptsRoot: bytesToPrefixedHexString(await builder.receiptTrie()), + logsHash: bytesToPrefixedHexString(logsHash), + logsBloom: bytesToPrefixedHexString(logsBloom), currentDifficulty: '0x20000', receipts, // TODO fixme } diff --git a/packages/vm/test/tester/runners/BlockchainTestsRunner.ts b/packages/vm/test/tester/runners/BlockchainTestsRunner.ts index c24f785d82..4dc1cc65ce 100644 --- a/packages/vm/test/tester/runners/BlockchainTestsRunner.ts +++ b/packages/vm/test/tester/runners/BlockchainTestsRunner.ts @@ -4,7 +4,8 @@ import { ConsensusAlgorithm, Hardfork } from '@ethereumjs/common' import { RLP } from '@ethereumjs/rlp' import { Trie } from '@ethereumjs/trie' import { TransactionFactory } from '@ethereumjs/tx' -import { bufferToBigInt, isHexPrefixed, stripHexPrefix, toBuffer } from '@ethereumjs/util' +import { bytesToBigInt, isHexPrefixed, stripHexPrefix, toBytes } from '@ethereumjs/util' +import { bytesToHex, hexToBytes } from 'ethereum-cryptography/utils' import { Level } from 'level' import { MemoryLevel } from 'memory-level' @@ -62,8 +63,8 @@ export async function runBlockchainTest(options: any, testData: any, t: tape.Tes const genesisBlock = Block.fromBlockData(blockData, { common }) if (typeof testData.genesisRLP === 'string') { - const rlp = toBuffer(testData.genesisRLP) - t.ok(genesisBlock.serialize().equals(rlp), 'correct genesis RLP') + const rlp = toBytes(testData.genesisRLP) + t.deepEquals(genesisBlock.serialize(), rlp, 'correct genesis RLP') } const blockchain = await Blockchain.create({ @@ -97,7 +98,7 @@ export async function runBlockchainTest(options: any, testData: any, t: tape.Tes // set up pre-state await setupPreConditions(vm.eei, testData) - t.ok(vm.stateManager._trie.root().equals(genesisBlock.header.stateRoot), 'correct pre stateRoot') + t.deepEquals(vm.stateManager._trie.root(), genesisBlock.header.stateRoot, 'correct pre stateRoot') async function handleError(error: string | undefined, expectException: string | boolean) { if (expectException !== false) { @@ -122,16 +123,16 @@ export async function runBlockchainTest(options: any, testData: any, t: tape.Tes // Here we decode the rlp to extract the block number // The block library cannot be used, as this throws on certain EIP1559 blocks when trying to convert try { - const blockRlp = Buffer.from((raw.rlp as string).slice(2), 'hex') + const blockRlp = hexToBytes((raw.rlp as string).slice(2)) const decodedRLP: any = RLP.decode(Uint8Array.from(blockRlp)) - currentBlock = bufferToBigInt(decodedRLP[0][8]) + currentBlock = bytesToBigInt(decodedRLP[0][8]) } catch (e: any) { await handleError(e, expectException) continue } try { - const blockRlp = Buffer.from((raw.rlp as string).slice(2), 'hex') + const blockRlp = hexToBytes((raw.rlp as string).slice(2)) // Update common HF let TD: bigint | undefined = undefined let timestamp: bigint | undefined = undefined @@ -139,7 +140,7 @@ export async function runBlockchainTest(options: any, testData: any, t: tape.Tes const decoded: any = RLP.decode(blockRlp) const parentHash = decoded[0][0] TD = await blockchain.getTotalDifficulty(parentHash) - timestamp = bufferToBigInt(decoded[0][11]) + timestamp = bytesToBigInt(decoded[0][11]) // eslint-disable-next-line no-empty } catch (e) {} @@ -160,7 +161,7 @@ export async function runBlockchainTest(options: any, testData: any, t: tape.Tes >[]) { const shouldFail = txData.valid === 'false' try { - const txRLP = Buffer.from(txData.rawBytes.slice(2), 'hex') + const txRLP = hexToBytes(txData.rawBytes.slice(2)) const tx = TransactionFactory.fromSerializedData(txRLP, { common }) await blockBuilder.addTransaction(tx) if (shouldFail) { @@ -229,7 +230,7 @@ export async function runBlockchainTest(options: any, testData: any, t: tape.Tes } } t.equal( - (blockchain as any)._headHeaderHash.toString('hex'), + bytesToHex((blockchain as any)._headHeaderHash), testData.lastblockhash, 'correct last header block' ) diff --git a/packages/vm/test/tester/runners/GeneralStateTestsRunner.ts b/packages/vm/test/tester/runners/GeneralStateTestsRunner.ts index bc658381e1..d86fe02f53 100644 --- a/packages/vm/test/tester/runners/GeneralStateTestsRunner.ts +++ b/packages/vm/test/tester/runners/GeneralStateTestsRunner.ts @@ -2,7 +2,7 @@ import { Block } from '@ethereumjs/block' import { Blockchain } from '@ethereumjs/blockchain' import { DefaultStateManager } from '@ethereumjs/statemanager' import { Trie } from '@ethereumjs/trie' -import { Address, toBuffer } from '@ethereumjs/util' +import { Address, bytesToHex, equalsBytes, toBytes } from '@ethereumjs/util' import { EVM } from '../../../../evm/src' import { EEI } from '../../../src' @@ -100,7 +100,7 @@ async function runTestCase(options: any, testData: any, t: tape.Test) { } // Even if no txs are ran, coinbase should always be created - const coinbaseAddress = new Address(Buffer.from(testData.env.currentCoinbase.slice(2), 'hex')) + const coinbaseAddress = new Address(testData.env.currentCoinbase.slice(2)) const account = await (vm).eei.getAccount(coinbaseAddress) await (vm).eei.putAccount(coinbaseAddress, account) @@ -129,7 +129,7 @@ async function runTestCase(options: any, testData: any, t: tape.Test) { }) vm.events.on('afterTx', async () => { const stateRoot = { - stateRoot: vm.stateManager._trie.root.toString('hex'), + stateRoot: bytesToHex(vm.stateManager._trie.root), } t.comment(JSON.stringify(stateRoot)) }) @@ -150,8 +150,8 @@ async function runTestCase(options: any, testData: any, t: tape.Test) { await (vm).eei.getStateRoot() // Ensure state root is updated (flush all changes to trie) const stateManagerStateRoot = vm.stateManager._trie.root() - const testDataPostStateRoot = toBuffer(testData.postStateRoot) - const stateRootsAreEqual = stateManagerStateRoot.equals(testDataPostStateRoot) + const testDataPostStateRoot = toBytes(testData.postStateRoot) + const stateRootsAreEqual = equalsBytes(stateManagerStateRoot, testDataPostStateRoot) const end = Date.now() const timeSpent = `${(end - begin) / 1000} secs` diff --git a/packages/vm/test/tester/testLoader.ts b/packages/vm/test/tester/testLoader.ts index c5bda69380..35d96be47f 100644 --- a/packages/vm/test/tester/testLoader.ts +++ b/packages/vm/test/tester/testLoader.ts @@ -36,7 +36,7 @@ export async function getTests( } const fileCallback = async ( err: Error | undefined, - content: string | Buffer, + content: string | Uint8Array, fileName: string, next: Function ) => { @@ -46,7 +46,7 @@ export async function getTests( } const subDir = fileName.substr(directory.length + 1) const parsedFileName = path.parse(fileName).name - content = Buffer.isBuffer(content) ? content.toString() : content + content = content instanceof Uint8Array ? content.toString() : content const testsByName = JSON.parse(content) const testNames = Object.keys(testsByName) for (const testName of testNames) { diff --git a/packages/vm/test/util.ts b/packages/vm/test/util.ts index 35f869b543..f6e1978661 100644 --- a/packages/vm/test/util.ts +++ b/packages/vm/test/util.ts @@ -9,16 +9,16 @@ import { import { Account, Address, - bigIntToBuffer, - bufferToBigInt, - bufferToHex, + bigIntToBytes, + bytesToBigInt, + bytesToPrefixedHexString, isHexPrefixed, setLengthLeft, stripHexPrefix, - toBuffer, + toBytes, } from '@ethereumjs/util' import { keccak256 } from 'ethereum-cryptography/keccak' -import { bytesToHex } from 'ethereum-cryptography/utils' +import { bytesToHex, equalsBytes, hexToBytes } from 'ethereum-cryptography/utils' import type { VmState } from '../src/eei/vmState' import type { BlockOptions } from '@ethereumjs/block' @@ -49,7 +49,7 @@ export function dumpState(state: any, cb: Function) { const storageRS = storageTrie.createReadStream() storageRS.on('data', function (data: any) { - storage[data.key.toString('hex')] = data.value.toString('hex') + storage[bytesToHex(data.key)] = bytesToHex(data.value) }) storageRS.on('end', function () { @@ -65,8 +65,8 @@ export function dumpState(state: any, cb: Function) { results.push(result) } for (let i = 0; i < results.length; i++) { - console.log("SHA3'd address: " + bufferToHex(results[i].address)) - console.log('\tstorage root: ' + bufferToHex(results[i].storageRoot)) + console.log("SHA3'd address: " + bytesToHex(results[i].address)) + console.log('\tstorage root: ' + bytesToHex(results[i].storageRoot)) console.log('\tstorage: ') for (const storageKey in results[i].storage) { console.log('\t\t' + storageKey + ': ' + results[i].storage[storageKey]) @@ -78,28 +78,28 @@ export function dumpState(state: any, cb: Function) { }) } -export function format(a: any, toZero: boolean = false, isHex: boolean = false): Buffer { +export function format(a: any, toZero: boolean = false, isHex: boolean = false): Uint8Array { if (a === '') { - return Buffer.alloc(0) + return new Uint8Array() } if (typeof a === 'string' && isHexPrefixed(a)) { a = a.slice(2) if (a.length % 2) a = '0' + a - a = Buffer.from(a, 'hex') + a = hexToBytes(a) } else if (!isHex) { try { - a = bigIntToBuffer(BigInt(a)) + a = bigIntToBytes(BigInt(a)) } catch { // pass } } else { if (a.length % 2) a = '0' + a - a = Buffer.from(a, 'hex') + a = hexToBytes(a) } - if (toZero && a.toString('hex') === '') { - a = Buffer.from([0]) + if (toZero && bytesToHex(a) === '') { + a = Uint8Array.from([0]) } return a @@ -125,7 +125,7 @@ export function makeTx( } if (txData.secretKey !== undefined) { - const privKey = toBuffer(txData.secretKey) + const privKey = toBytes(txData.secretKey) return tx.sign(privKey) } @@ -138,7 +138,7 @@ export async function verifyPostConditions(state: any, testData: any, t: tape.Te const keyMap: any = {} for (const key in testData) { - const hash = bytesToHex(keccak256(Buffer.from(stripHexPrefix(key), 'hex'))) + const hash = bytesToHex(keccak256(hexToBytes(stripHexPrefix(key)))) hashedAccounts[hash] = testData[key] keyMap[hash] = key } @@ -150,7 +150,7 @@ export async function verifyPostConditions(state: any, testData: any, t: tape.Te stream.on('data', function (data: any) { const rlp = data.value const account = Account.fromRlpSerializedAccount(rlp) - const key = data.key.toString('hex') + const key = bytesToHex(data.key) const testData = hashedAccounts[key] const address = keyMap[key] delete keyMap[key] @@ -189,18 +189,16 @@ export function verifyAccountPostConditions( ) { return new Promise((resolve) => { t.comment('Account: ' + address) - if (!format(account.balance, true).equals(format(acctData.balance, true))) { + if (!equalsBytes(format(account.balance, true), format(acctData.balance, true))) { t.comment( - `Expected balance of ${bufferToBigInt(format(acctData.balance, true))}, but got ${ + `Expected balance of ${bytesToBigInt(format(acctData.balance, true))}, but got ${ account.balance }` ) } - if (!format(account.nonce, true).equals(format(acctData.nonce, true))) { + if (!equalsBytes(format(account.nonce, true), format(acctData.nonce, true))) { t.comment( - `Expected nonce of ${bufferToBigInt(format(acctData.nonce, true))}, but got ${ - account.nonce - }` + `Expected nonce of ${bytesToBigInt(format(acctData.nonce, true))}, but got ${account.nonce}` ) } @@ -209,15 +207,15 @@ export function verifyAccountPostConditions( const hashedStorage: any = {} for (const key in acctData.storage) { - hashedStorage[bytesToHex(keccak256(setLengthLeft(Buffer.from(key.slice(2), 'hex'), 32)))] = + hashedStorage[bytesToHex(keccak256(setLengthLeft(hexToBytes(key.slice(2)), 32)))] = acctData.storage[key] } state.root(account.storageRoot) const rs = state.createReadStream() rs.on('data', function (data: any) { - let key = data.key.toString('hex') - const val = '0x' + Buffer.from(RLP.decode(data.value) as Uint8Array).toString('hex') + let key = bytesToHex(data.key) + const val = bytesToPrefixedHexString(RLP.decode(data.value) as Uint8Array) if (key === '0x') { key = '0x00' @@ -227,7 +225,7 @@ export function verifyAccountPostConditions( if (val !== hashedStorage[key]) { t.comment( - `Expected storage key 0x${data.key.toString('hex')} at address ${address} to have value ${ + `Expected storage key 0x${bytesToHex(data.key)} at address ${address} to have value ${ hashedStorage[key] ?? '0x' }, but got ${val}}` ) @@ -344,7 +342,7 @@ export async function setupPreConditions(state: VmState, testData: any) { // Set contract storage for (const storageKey of Object.keys(storage)) { const val = format(storage[storageKey]) - if (['', '00'].includes(val.toString('hex'))) { + if (['', '00'].includes(bytesToHex(val))) { continue } const key = setLengthLeft(format(storageKey), 32) From 802c1c276ec853ff9777f707b50d34c5ccf6414b Mon Sep 17 00:00:00 2001 From: acolytec3 <17355484+acolytec3@users.noreply.github.com> Date: Tue, 4 Apr 2023 11:36:02 -0400 Subject: [PATCH 02/53] Buffer to Uint8Array cleanup (#2607) * `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 * Fix test runner * remove console log --------- Co-authored-by: Holger Drewes Co-authored-by: g11tech Co-authored-by: Jochem Brouwer Co-authored-by: Gabriel Rocheleau --- packages/blockchain/src/db/manager.ts | 13 ++- packages/blockchain/src/db/operation.ts | 2 +- packages/client/lib/config.ts | 2 +- packages/client/lib/execution/level.ts | 2 +- .../client/lib/net/protocol/snapprotocol.ts | 4 +- packages/client/lib/net/server/rlpxserver.ts | 8 +- .../client/lib/sync/fetcher/accountfetcher.ts | 2 +- packages/client/lib/util/metaDBManager.ts | 2 +- packages/client/test/integration/pow.spec.ts | 97 +++++++++++++++++++ .../test/sync/fetcher/storagefetcher.spec.ts | 2 +- packages/devp2p/examples/simple.ts | 2 +- packages/devp2p/src/protocol/eth.ts | 2 +- packages/devp2p/src/rlpx/peer.ts | 4 +- packages/devp2p/src/util.ts | 2 +- packages/ethash/src/index.ts | 3 + packages/ethash/test/miner.spec.ts | 12 +-- packages/evm/src/memory.ts | 2 +- .../evm/src/precompiles/0a-bls12-g1add.ts | 2 +- .../evm/src/precompiles/0b-bls12-g1mul.ts | 2 +- .../evm/src/precompiles/0d-bls12-g2add.ts | 2 +- .../evm/src/precompiles/0e-bls12-g2mul.ts | 2 +- .../evm/src/precompiles/util/bls12_381.ts | 14 +-- packages/trie/benchmarks/engines/level.ts | 2 +- packages/trie/recipes/level-legacy.ts | 2 +- packages/trie/recipes/level.ts | 2 +- packages/tx/src/types.ts | 6 +- packages/util/src/bytes.ts | 2 +- packages/util/src/types.ts | 2 +- packages/util/test/account.spec.ts | 32 +++--- packages/util/test/bytes.spec.ts | 4 +- .../tester/runners/GeneralStateTestsRunner.ts | 2 +- 31 files changed, 170 insertions(+), 67 deletions(-) create mode 100644 packages/client/test/integration/pow.spec.ts diff --git a/packages/blockchain/src/db/manager.ts b/packages/blockchain/src/db/manager.ts index d84911091a..ec099111ba 100644 --- a/packages/blockchain/src/db/manager.ts +++ b/packages/blockchain/src/db/manager.ts @@ -65,7 +65,11 @@ export class DBManager { async getHeads(): Promise<{ [key: string]: Uint8Array }> { const heads = await this.get(DBTarget.Heads) for (const key of Object.keys(heads)) { - heads[key] = Uint8Array.from(heads[key]) + // DB incorrectly stores the `uint8Array` representation of each head hash + // as a JSON object of key value pairs where the key is the array index + // and the value is the uint8 from that index of the original array + // so we convert it back to a Uint8Array before storing the heads + heads[key] = Uint8Array.from(Object.values(heads[key])) } return heads } @@ -213,13 +217,13 @@ export class DBManager { if (this._cache[cacheString] === undefined) { throw new Error(`Invalid cache: ${cacheString}`) } - let value = this._cache[cacheString].get(dbKey) if (!value) { value = await this._db.get(dbKey, dbOpts) - if (value) { - this._cache[cacheString].set(dbKey, value) + if (value !== undefined) { + // Always cast values to Uint8Array since db sometimes returns values as `Buffer` + this._cache[cacheString].set(dbKey, Uint8Array.from(value)) } } @@ -236,7 +240,6 @@ export class DBManager { const convertedOps: DBOpData[] = ops.map((op) => op.baseDBOp) // update the current cache for each operation ops.map((op) => op.updateCache(this._cache)) - return this._db.batch(convertedOps as any) } } diff --git a/packages/blockchain/src/db/operation.ts b/packages/blockchain/src/db/operation.ts index 4a6cfa9c1a..84730ba853 100644 --- a/packages/blockchain/src/db/operation.ts +++ b/packages/blockchain/src/db/operation.ts @@ -119,7 +119,7 @@ export class DBOp { if (operationTarget === DBTarget.Heads) { dbOperation.baseDBOp.valueEncoding = 'json' } else { - dbOperation.baseDBOp.valueEncoding = 'binary' + dbOperation.baseDBOp.valueEncoding = 'view' } return dbOperation diff --git a/packages/client/lib/config.ts b/packages/client/lib/config.ts index 571f64667f..13b2c0e582 100644 --- a/packages/client/lib/config.ts +++ b/packages/client/lib/config.ts @@ -539,7 +539,7 @@ export class Config { static async getClientKey(datadir: string, common: Common) { const networkDir = `${datadir}/${common.chainName()}` const db = this.getConfigDB(networkDir) - const encodingOpts = { keyEncoding: 'utf8', valueEncoding: 'buffer' } + const encodingOpts = { keyEncoding: 'utf8', valueEncoding: 'view' } const dbKey = 'config:client_key' let key try { diff --git a/packages/client/lib/execution/level.ts b/packages/client/lib/execution/level.ts index 08398f739d..78f88a5ad6 100644 --- a/packages/client/lib/execution/level.ts +++ b/packages/client/lib/execution/level.ts @@ -3,7 +3,7 @@ import { MemoryLevel } from 'memory-level' import type { BatchDBOp, DB } from '@ethereumjs/trie' import type { AbstractLevel } from 'abstract-level' -export const ENCODING_OPTS = { keyEncoding: 'buffer', valueEncoding: 'buffer' } +export const ENCODING_OPTS = { keyEncoding: 'view', valueEncoding: 'view' } /** * LevelDB is a thin wrapper around the underlying levelup db, diff --git a/packages/client/lib/net/protocol/snapprotocol.ts b/packages/client/lib/net/protocol/snapprotocol.ts index 6dc738d56c..92a212be08 100644 --- a/packages/client/lib/net/protocol/snapprotocol.ts +++ b/packages/client/lib/net/protocol/snapprotocol.ts @@ -87,8 +87,8 @@ export interface SnapProtocolMethods { slots: StorageData[][] proof: Uint8Array[] }> - getByteCodes: (opts: GetByteCodesOpts) => Promise<{ reqId: bigint; codes: Buffer[] }> - getTrieNodes: (opts: GetTrieNodesOpts) => Promise<{ reqId: bigint; nodes: Buffer[] }> + getByteCodes: (opts: GetByteCodesOpts) => Promise<{ reqId: bigint; codes: Uint8Array[] }> + getTrieNodes: (opts: GetTrieNodesOpts) => Promise<{ reqId: bigint; nodes: Uint8Array[] }> } /** diff --git a/packages/client/lib/net/server/rlpxserver.ts b/packages/client/lib/net/server/rlpxserver.ts index 9d5f90eb6f..7180f2e0d8 100644 --- a/packages/client/lib/net/server/rlpxserver.ts +++ b/packages/client/lib/net/server/rlpxserver.ts @@ -282,13 +282,7 @@ export class RlpxServer extends Server { } }) - this.rlpx.on('peer:error', (rlpxPeer: Devp2pRLPxPeer, error: Error) => { - const peerId = bytesToHex(rlpxPeer.getId() as Uint8Array) - if (peerId === null) { - return this.error(error) - } - this.error(error) - }) + this.rlpx.on('peer:error', (rlpxPeer: Devp2pRLPxPeer, error: Error) => this.error(error)) this.rlpx.on('error', (e: Error) => this.error(e)) diff --git a/packages/client/lib/sync/fetcher/accountfetcher.ts b/packages/client/lib/sync/fetcher/accountfetcher.ts index 5ef539f596..eb680b38af 100644 --- a/packages/client/lib/sync/fetcher/accountfetcher.ts +++ b/packages/client/lib/sync/fetcher/accountfetcher.ts @@ -359,7 +359,7 @@ export class AccountFetcher extends Fetcher // build record of accounts that need storage slots to be fetched const storageRoot: Uint8Array = account.body[2] instanceof Uint8Array ? account.body[2] : Uint8Array.from(account.body[2]) - if (equalsBytes(storageRoot, KECCAK256_RLP)) { + if (!equalsBytes(storageRoot, KECCAK256_RLP)) { storageFetchRequests.push({ accountHash: account.hash, storageRoot, diff --git a/packages/client/lib/util/metaDBManager.ts b/packages/client/lib/util/metaDBManager.ts index c20feb68bd..dc067a6547 100644 --- a/packages/client/lib/util/metaDBManager.ts +++ b/packages/client/lib/util/metaDBManager.ts @@ -4,7 +4,7 @@ import type { Chain } from '../blockchain' import type { Config } from '../config' import type { AbstractLevel } from 'abstract-level' -const encodingOpts = { keyEncoding: 'buffer', valueEncoding: 'buffer' } +const encodingOpts = { keyEncoding: 'view', valueEncoding: 'view' } /** * Number prepended to the db key to avoid collisions diff --git a/packages/client/test/integration/pow.spec.ts b/packages/client/test/integration/pow.spec.ts new file mode 100644 index 0000000000..5ff93dda3c --- /dev/null +++ b/packages/client/test/integration/pow.spec.ts @@ -0,0 +1,97 @@ +import { parseGethGenesisState } from '@ethereumjs/blockchain' +import { Common, Hardfork } from '@ethereumjs/common' +import { Address } from '@ethereumjs/util' +import { hexToBytes } from 'ethereum-cryptography/utils' +import { removeSync } from 'fs-extra' +import * as tape from 'tape' + +import { Config } from '../../lib' +import { createInlineClient } from '../sim/simutils' + +import type { EthereumClient } from '../../lib' + +const pk = hexToBytes('95a602ff1ae30a2243f400dcf002561b9743b2ae9827b1008e3714a5cc1c0cfe') +const minerAddress = Address.fromPrivateKey(pk) + +async function setupPowDevnet(prefundAddress: Address, cleanStart: boolean) { + if (cleanStart) { + removeSync(`datadir/devnet`) + } + const addr = prefundAddress.toString().slice(2) + const consensusConfig = { ethash: true } + + const defaultChainData = { + config: { + chainId: 123456, + homesteadBlock: 0, + eip150Block: 0, + eip150Hash: '0x0000000000000000000000000000000000000000000000000000000000000000', + eip155Block: 0, + eip158Block: 0, + byzantiumBlock: 0, + constantinopleBlock: 0, + petersburgBlock: 0, + istanbulBlock: 0, + berlinBlock: 0, + londonBlock: 0, + ...consensusConfig, + }, + nonce: '0x0', + timestamp: '0x614b3731', + gasLimit: '0x47b760', + difficulty: '0x1', + mixHash: '0x0000000000000000000000000000000000000000000000000000000000000000', + coinbase: '0x0000000000000000000000000000000000000000', + number: '0x0', + gasUsed: '0x0', + parentHash: '0x0000000000000000000000000000000000000000000000000000000000000000', + baseFeePerGas: 7, + } + const extraData = '0x' + '0'.repeat(32) + const chainData = { + ...defaultChainData, + extraData, + alloc: { [addr]: { balance: '0x10000000000000000000' } }, + } + const common = Common.fromGethGenesis(chainData, { chain: 'devnet', hardfork: Hardfork.London }) + const customGenesisState = parseGethGenesisState(chainData) + + const config = new Config({ + common, + transports: ['rlpx'], + bootnodes: [], + multiaddrs: [], + discDns: false, + discV4: false, + port: 30304, + maxAccountRange: (BigInt(2) ** BigInt(256) - BigInt(1)) / BigInt(10), + maxFetcherJobs: 10, + datadir: 'devnet', + accounts: [[minerAddress, pk]], + mine: true, + }) + + const client = await createInlineClient(config, common, customGenesisState) + return client +} + +const mineBlockAndstopClient = async (client: EthereumClient, t: tape.Test) => { + await new Promise((resolve) => { + client.config.logger.on('data', (data) => { + if (data.message.includes('Miner: Found PoW solution') === true && client.started) { + t.pass('found a PoW solution') + void client.stop().then(() => { + t.ok(!client.started, 'client stopped successfully') + resolve(undefined) + }) + } + }) + }) +} + +tape('PoW client test', { timeout: 60000 }, async (t) => { + t.plan(3) + const client = await setupPowDevnet(minerAddress, true) + t.ok(client.started, 'client started successfully') + await mineBlockAndstopClient(client, t) +}) diff --git a/packages/client/test/sync/fetcher/storagefetcher.spec.ts b/packages/client/test/sync/fetcher/storagefetcher.spec.ts index 168b2fe0ed..6cc76198c1 100644 --- a/packages/client/test/sync/fetcher/storagefetcher.spec.ts +++ b/packages/client/test/sync/fetcher/storagefetcher.spec.ts @@ -306,7 +306,7 @@ tape('[StorageFetcher]', async (t) => { const dummyStorageRoot = hexToBytes( '39ed8daab7679c0b1b7cf3667c50108185d4d9d1431c24a1c35f696a58277f8f' ) - const dummyOrigin = Buffer.alloc(32) + const dummyOrigin = new Uint8Array(32) try { await fetcher['verifyRangeProof'](dummyStorageRoot, dummyOrigin, { slots, diff --git a/packages/devp2p/examples/simple.ts b/packages/devp2p/examples/simple.ts index 8cf80e3c1c..8a4c2fa870 100644 --- a/packages/devp2p/examples/simple.ts +++ b/packages/devp2p/examples/simple.ts @@ -1,6 +1,6 @@ import { Chain, Common } from '@ethereumjs/common' import chalk from 'chalk' -import { hexToBytes } from 'ethereum-cryptography/utils' +import { bytesToHex, hexToBytes } from 'ethereum-cryptography/utils' import { DPT } from '../src/index' diff --git a/packages/devp2p/src/protocol/eth.ts b/packages/devp2p/src/protocol/eth.ts index 1b88a27b04..74ffc3e8d5 100644 --- a/packages/devp2p/src/protocol/eth.ts +++ b/packages/devp2p/src/protocol/eth.ts @@ -227,7 +227,7 @@ export class ETH extends Protocol { _getStatusString(status: ETH.StatusMsg) { let sStr = `[V:${bytesToInt(status[0] as Uint8Array)}, NID:${bytesToInt( status[1] as Uint8Array - )}, TD:${status[2].length === 0 ? 0 : bytesToInt(status[2] as Uint8Array)}` + )}, TD:${status[2].length === 0 ? 0 : bytesToBigInt(status[2] as Uint8Array).toString()}` sStr += `, BestH:${formatLogId( bytesToHex(status[3] as Uint8Array), this._verbose diff --git a/packages/devp2p/src/rlpx/peer.ts b/packages/devp2p/src/rlpx/peer.ts index 06adf22e37..1df28c1689 100644 --- a/packages/devp2p/src/rlpx/peer.ts +++ b/packages/devp2p/src/rlpx/peer.ts @@ -587,11 +587,11 @@ export class Peer extends EventEmitter { // if (protocolName === 'Peer') { try { - payload = RLP.decode(Uint8Array.from(payload)) + payload = RLP.decode(payload) } catch (e: any) { if (msgCode === PREFIXES.DISCONNECT) { if (compressed) { - payload = RLP.decode(Uint8Array.from(origPayload)) + payload = RLP.decode(origPayload) } else { payload = RLP.decode(snappy.uncompress(payload)) } diff --git a/packages/devp2p/src/util.ts b/packages/devp2p/src/util.ts index fa0afc447c..a744dd96fd 100644 --- a/packages/devp2p/src/util.ts +++ b/packages/devp2p/src/util.ts @@ -126,7 +126,7 @@ export function toNewUint8Array(buf: Uint8Array): Uint8Array { /*************************** ************************************************************/ // Methods borrowed from `node-ip` by Fedor Indutny (https://github.com/indutny/node-ip) -// and modified to use Uint8Arrays instead of Buffers +// and modified to use Uint8Arrays instead of Uint8Arrays export const ipToString = (bytes: Uint8Array, offset?: number, length?: number) => { offset = offset !== undefined ? ~~offset : 0 length = length ?? bytes.length - offset diff --git a/packages/ethash/src/index.ts b/packages/ethash/src/index.ts index 88c7885214..7074101005 100644 --- a/packages/ethash/src/index.ts +++ b/packages/ethash/src/index.ts @@ -318,6 +318,9 @@ export class Ethash { let data try { data = await this.cacheDB!.get(epoc, this.dbOpts) + // Fix uint8Arrays that get stored in DB as JSON dictionary of array indices and values + data.seed = Uint8Array.from(Object.values(data.seed)) + data.cache = data.cache.map((el) => Uint8Array.from(Object.values(el))) } catch (error: any) { if (error.code !== 'LEVEL_NOT_FOUND') { throw error diff --git a/packages/ethash/test/miner.spec.ts b/packages/ethash/test/miner.spec.ts index 5bd1e035cc..2d01dd51c3 100644 --- a/packages/ethash/test/miner.spec.ts +++ b/packages/ethash/test/miner.spec.ts @@ -6,11 +6,11 @@ import * as tape from 'tape' import { Ethash } from '../src' import type { BlockHeader } from '@ethereumjs/block' - +const cacheDb = new MemoryLevel() const common = new Common({ chain: Chain.Ropsten, hardfork: Hardfork.Petersburg }) tape('Check if miner works as expected', async function (t) { - const e = new Ethash(new MemoryLevel()) + const e = new Ethash(cacheDb as any) const block = Block.fromBlockData( { @@ -54,7 +54,7 @@ tape('Check if miner works as expected', async function (t) { }) tape('Check if it is possible to mine Blocks and BlockHeaders', async function (t) { - const e = new Ethash(new MemoryLevel()) + const e = new Ethash(cacheDb as any) const block = Block.fromBlockData( { @@ -82,7 +82,7 @@ tape('Check if it is possible to mine Blocks and BlockHeaders', async function ( }) tape('Check if it is possible to stop the miner', async function (t) { - const e = new Ethash(new MemoryLevel()) + const e = new Ethash(cacheDb as any) const block = Block.fromBlockData( { @@ -104,7 +104,7 @@ tape('Check if it is possible to stop the miner', async function (t) { }) tape('Check if it is possible to stop the miner', async function (t) { - const e = new Ethash(new MemoryLevel()) + const e = new Ethash(cacheDb as any) const block: any = {} @@ -116,7 +116,7 @@ tape('Check if it is possible to stop the miner', async function (t) { }) tape('Should keep common when mining blocks or headers', async function (t) { - const e = new Ethash(new MemoryLevel()) + const e = new Ethash(cacheDb as any) const block = Block.fromBlockData( { diff --git a/packages/evm/src/memory.ts b/packages/evm/src/memory.ts index 85eafd0604..de06282c5d 100644 --- a/packages/evm/src/memory.ts +++ b/packages/evm/src/memory.ts @@ -75,7 +75,7 @@ export class Memory { return loaded } const returnBytes = new Uint8Array(size) - // Copy the stored "buffer" from memory into the return Buffer + // Copy the stored "buffer" from memory into the return Uint8Array returnBytes.set(loaded) return returnBytes diff --git a/packages/evm/src/precompiles/0a-bls12-g1add.ts b/packages/evm/src/precompiles/0a-bls12-g1add.ts index edbd32748c..1388851876 100644 --- a/packages/evm/src/precompiles/0a-bls12-g1add.ts +++ b/packages/evm/src/precompiles/0a-bls12-g1add.ts @@ -57,7 +57,7 @@ export async function precompile0a(opts: PrecompileInput): Promise { } } - // convert input to mcl G1 points, add them, and convert the output to a Buffer. + // convert input to mcl G1 points, add them, and convert the output to a Uint8Array. let mclPoint1 let mclPoint2 try { diff --git a/packages/evm/src/precompiles/0b-bls12-g1mul.ts b/packages/evm/src/precompiles/0b-bls12-g1mul.ts index b6253c48da..b006d88ea1 100644 --- a/packages/evm/src/precompiles/0b-bls12-g1mul.ts +++ b/packages/evm/src/precompiles/0b-bls12-g1mul.ts @@ -59,7 +59,7 @@ export async function precompile0b(opts: PrecompileInput): Promise { } } - // convert input to mcl G1 points, add them, and convert the output to a Buffer. + // convert input to mcl G1 points, add them, and convert the output to a Uint8Array. let mclPoint try { diff --git a/packages/evm/src/precompiles/0d-bls12-g2add.ts b/packages/evm/src/precompiles/0d-bls12-g2add.ts index 3fdb64351c..620bf61673 100644 --- a/packages/evm/src/precompiles/0d-bls12-g2add.ts +++ b/packages/evm/src/precompiles/0d-bls12-g2add.ts @@ -63,7 +63,7 @@ export async function precompile0d(opts: PrecompileInput): Promise { // TODO: verify that point is on G2 - // convert input to mcl G2 points, add them, and convert the output to a Buffer. + // convert input to mcl G2 points, add them, and convert the output to a Uint8Array. let mclPoint1 let mclPoint2 diff --git a/packages/evm/src/precompiles/0e-bls12-g2mul.ts b/packages/evm/src/precompiles/0e-bls12-g2mul.ts index 1b25251d65..546e1964a4 100644 --- a/packages/evm/src/precompiles/0e-bls12-g2mul.ts +++ b/packages/evm/src/precompiles/0e-bls12-g2mul.ts @@ -63,7 +63,7 @@ export async function precompile0e(opts: PrecompileInput): Promise { // TODO: verify that point is on G2 - // convert input to mcl G2 point/Fr point, add them, and convert the output to a Buffer. + // convert input to mcl G2 point/Fr point, add them, and convert the output to a Uint8Array. let mclPoint try { mclPoint = BLS12_381_ToG2Point(opts.data.subarray(0, 256), mcl) diff --git a/packages/evm/src/precompiles/util/bls12_381.ts b/packages/evm/src/precompiles/util/bls12_381.ts index 0fe8b79814..b307a51b6c 100644 --- a/packages/evm/src/precompiles/util/bls12_381.ts +++ b/packages/evm/src/precompiles/util/bls12_381.ts @@ -139,8 +139,8 @@ export const gasDiscountPairs = [ [127, 175], [128, 174], ] -// convert an input Buffer to a mcl G1 point -// this does /NOT/ do any input checks. the input Buffer needs to be of length 128 +// convert an input Uint8Array to a mcl G1 point +// this does /NOT/ do any input checks. the input Uint8Array needs to be of length 128 // it does raise an error if the point is not on the curve. function BLS12_381_ToG1Point(input: Uint8Array, mcl: any): any { const p_x = bytesToHex(input.subarray(16, 64)) @@ -178,7 +178,7 @@ function BLS12_381_ToG1Point(input: Uint8Array, mcl: any): any { } // input: a mcl G1 point -// output: a 128-byte Buffer +// output: a 128-byte Uint8Array function BLS12_381_FromG1Point(input: any): Uint8Array { // TODO: figure out if there is a better way to decode these values. const decodeStr = input.getStr(16) //return a string of pattern "1 " @@ -200,8 +200,8 @@ function BLS12_381_FromG1Point(input: any): Uint8Array { return concatBytesNoTypeCheck(xBuffer, yBuffer) } -// convert an input Buffer to a mcl G2 point -// this does /NOT/ do any input checks. the input Buffer needs to be of length 256 +// convert an input Uint8Array to a mcl G2 point +// this does /NOT/ do any input checks. the input Uint8Array needs to be of length 256 function BLS12_381_ToG2Point(input: Uint8Array, mcl: any): any { const p_x_1 = input.subarray(0, 64) const p_x_2 = input.subarray(64, 128) @@ -251,7 +251,7 @@ function BLS12_381_ToG2Point(input: Uint8Array, mcl: any): any { } // input: a mcl G2 point -// output: a 256-byte Buffer +// output: a 256-byte Uint8Array function BLS12_381_FromG2Point(input: any): Uint8Array { // TODO: figure out if there is a better way to decode these values. const decodeStr = input.getStr(16) //return a string of pattern "1 " @@ -276,7 +276,7 @@ function BLS12_381_FromG2Point(input: any): Uint8Array { return concatBytesNoTypeCheck(xBuffer1, xBuffer2, yBuffer1, yBuffer2) } -// input: a 32-byte hex scalar Buffer +// input: a 32-byte hex scalar Uint8Array // output: a mcl Fr point function BLS12_381_ToFrPoint(input: Uint8Array, mcl: any): any { diff --git a/packages/trie/benchmarks/engines/level.ts b/packages/trie/benchmarks/engines/level.ts index e172c9adfe..0064b15e2c 100644 --- a/packages/trie/benchmarks/engines/level.ts +++ b/packages/trie/benchmarks/engines/level.ts @@ -4,7 +4,7 @@ import { MemoryLevel } from 'memory-level' import type { BatchDBOp, DB } from '../../src/types' import type { AbstractLevel } from 'abstract-level' -export const ENCODING_OPTS = { keyEncoding: 'Uint8Array', valueEncoding: 'Uint8Array' } +export const ENCODING_OPTS = { keyEncoding: 'view', valueEncoding: 'view' } /** * LevelDB is a thin wrapper around the underlying levelup db, diff --git a/packages/trie/recipes/level-legacy.ts b/packages/trie/recipes/level-legacy.ts index 0040f87269..ff37097c8b 100644 --- a/packages/trie/recipes/level-legacy.ts +++ b/packages/trie/recipes/level-legacy.ts @@ -3,7 +3,7 @@ import level from 'level-mem' import type { BatchDBOp, DB } from '@ethereumjs/trie' import type { LevelUp } from 'levelup' -const ENCODING_OPTS = { keyEncoding: 'binary', valueEncoding: 'binary' } +const ENCODING_OPTS = { keyEncoding: 'view', valueEncoding: 'view' } export class LevelDB implements DB { readonly _leveldb: LevelUp diff --git a/packages/trie/recipes/level.ts b/packages/trie/recipes/level.ts index 6a7744a441..6d6814d70d 100644 --- a/packages/trie/recipes/level.ts +++ b/packages/trie/recipes/level.ts @@ -3,7 +3,7 @@ import { MemoryLevel } from 'memory-level' import type { BatchDBOp, DB } from '@ethereumjs/trie' import type { AbstractLevel } from 'abstract-level' -const ENCODING_OPTS = { keyEncoding: 'buffer', valueEncoding: 'buffer' } +const ENCODING_OPTS = { keyEncoding: 'view', valueEncoding: 'view' } export class LevelDB implements DB { readonly _leveldb: AbstractLevel< diff --git a/packages/tx/src/types.ts b/packages/tx/src/types.ts index ebc95b241f..ff1187624f 100644 --- a/packages/tx/src/types.ts +++ b/packages/tx/src/types.ts @@ -258,12 +258,12 @@ export interface BlobEIP4844TxData extends FeeMarketEIP1559TxData { } /** - * Buffer values array for a legacy {@link Transaction} + * Bytes values array for a legacy {@link Transaction} */ export type TxValuesArray = Uint8Array[] /** - * Buffer values array for an {@link AccessListEIP2930Transaction} + * Bytes values array for an {@link AccessListEIP2930Transaction} */ export type AccessListEIP2930ValuesArray = [ Uint8Array, @@ -280,7 +280,7 @@ export type AccessListEIP2930ValuesArray = [ ] /** - * Buffer values array for a {@link FeeMarketEIP1559Transaction} + * Bytes values array for a {@link FeeMarketEIP1559Transaction} */ export type FeeMarketEIP1559ValuesArray = [ Uint8Array, diff --git a/packages/util/src/bytes.ts b/packages/util/src/bytes.ts index e276b85b95..faaec5d480 100644 --- a/packages/util/src/bytes.ts +++ b/packages/util/src/bytes.ts @@ -334,7 +334,7 @@ export const toUtf8 = function (hex: string): string { * * Note: This method is useful for validating that RLP encoded integers comply with the rule that all * integer values encoded to RLP must be in the most compact form and contain no leading zero bytes - * @param values An object containing string keys and Buffer values + * @param values An object containing string keys and Uint8Array values * @throws if any provided value is found to have leading zero bytes */ export const validateNoLeadingZeroes = function (values: { diff --git a/packages/util/src/types.ts b/packages/util/src/types.ts index 1c4c6e4a4d..144672eb3c 100644 --- a/packages/util/src/types.ts +++ b/packages/util/src/types.ts @@ -12,7 +12,7 @@ import type { ToBytesInputTypes } from './bytes' export type BigIntLike = bigint | PrefixedHexString | number | Uint8Array /* - * A type that represents an input that can be converted to a Buffer. + * A type that represents an input that can be converted to a Uint8Array. */ export type BytesLike = | Uint8Array diff --git a/packages/util/test/account.spec.ts b/packages/util/test/account.spec.ts index 082d3a477b..d2856eb2fa 100644 --- a/packages/util/test/account.spec.ts +++ b/packages/util/test/account.spec.ts @@ -197,7 +197,7 @@ tape('Utility Functions', function (t) { st.notOk(isValidPrivate(hexToBytes(tmp)), 'should fail on too big input') st.notOk( - isValidPrivate(('WRONG_INPUT_TYPE') as Buffer), + isValidPrivate(('WRONG_INPUT_TYPE') as Uint8Array), 'should fail on wrong input type' ) @@ -311,8 +311,8 @@ tape('Utility Functions', function (t) { ) st.throws(function () { - importPublic((pubKey) as Buffer) - }, 'should throw if input is not Buffer') + importPublic((pubKey) as Uint8Array) + }, 'should throw if input is not Uint8Array') st.end() }) @@ -429,12 +429,18 @@ tape('Utility Functions', function (t) { t.test('generateAddress wt.testh non-buffer inputs', function (st) { st.throws(function () { - generateAddress(('0x990ccf8a0de58091c028d6ff76bb235ee67c1c39') as Buffer, toBytes(0)) - }, 'should throw if address is not Buffer') + generateAddress( + ('0x990ccf8a0de58091c028d6ff76bb235ee67c1c39') as Uint8Array, + toBytes(0) + ) + }, 'should throw if address is not Uint8Array') st.throws(function () { - generateAddress(toBytes('0x990ccf8a0de58091c028d6ff76bb235ee67c1c39'), (0) as Buffer) - }, 'should throw if nonce is not Buffer') + generateAddress( + toBytes('0x990ccf8a0de58091c028d6ff76bb235ee67c1c39'), + (0) as Uint8Array + ) + }, 'should throw if nonce is not Uint8Array') st.end() }) @@ -455,16 +461,16 @@ tape('Utility Functions', function (t) { const { address, salt, initCode } = eip1014Testdata[0] st.throws(function () { - generateAddress2((address) as Buffer, toBytes(salt), toBytes(initCode)) - }, 'should throw if address is not Buffer') + generateAddress2((address) as Uint8Array, toBytes(salt), toBytes(initCode)) + }, 'should throw if address is not Uint8Array') st.throws(function () { - generateAddress2(toBytes(address), (salt) as Buffer, toBytes(initCode)) - }, 'should throw if salt is not Buffer') + generateAddress2(toBytes(address), (salt) as Uint8Array, toBytes(initCode)) + }, 'should throw if salt is not Uint8Array') st.throws(function () { - generateAddress2(toBytes(address), toBytes(salt), (initCode) as Buffer) - }, 'should throw if initCode is not Buffer') + generateAddress2(toBytes(address), toBytes(salt), (initCode) as Uint8Array) + }, 'should throw if initCode is not Uint8Array') st.end() }) diff --git a/packages/util/test/bytes.spec.ts b/packages/util/test/bytes.spec.ts index 497ff4a2e0..ec7070f50c 100644 --- a/packages/util/test/bytes.spec.ts +++ b/packages/util/test/bytes.spec.ts @@ -123,7 +123,7 @@ tape('setLengthLeft', function (t) { }) t.test('should throw if input is not a Uint8Array', function (st) { st.throws(function () { - setLengthLeft(([9, 9]) as Buffer, 3) + setLengthLeft(([9, 9]) as Uint8Array, 3) }) st.end() }) @@ -273,7 +273,7 @@ tape('toUtf8', function (t) { tape('toBytes', function (t) { t.test('should work', function (st) { - // Buffer + // Uint8Array st.ok(equalsBytes(toBytes(new Uint8Array(0)), new Uint8Array())) // Array st.ok(equalsBytes(toBytes([]), new Uint8Array())) diff --git a/packages/vm/test/tester/runners/GeneralStateTestsRunner.ts b/packages/vm/test/tester/runners/GeneralStateTestsRunner.ts index d86fe02f53..00ba0b97f0 100644 --- a/packages/vm/test/tester/runners/GeneralStateTestsRunner.ts +++ b/packages/vm/test/tester/runners/GeneralStateTestsRunner.ts @@ -100,7 +100,7 @@ async function runTestCase(options: any, testData: any, t: tape.Test) { } // Even if no txs are ran, coinbase should always be created - const coinbaseAddress = new Address(testData.env.currentCoinbase.slice(2)) + const coinbaseAddress = Address.fromString(testData.env.currentCoinbase) const account = await (vm).eei.getAccount(coinbaseAddress) await (vm).eei.putAccount(coinbaseAddress, account) From 2bf1292ef30f5a3a36a91ce007385077527b648a Mon Sep 17 00:00:00 2001 From: Jochem Brouwer Date: Tue, 11 Apr 2023 00:16:02 +0200 Subject: [PATCH 03/53] Clique: get signers by block num (#2610) * blockchain/clique: add support for clique signers by block num * blockchain: clique sort clique latest signer states * client: fix build * blockchain/clique: fix tests and add test * blockchain/clique: fix clique bugs * blockchain/tests/clique: fix tests * blockchain: clique: add reorg test * blockchain/clique: add reorg over epoch test (fails) [no ci] * replace equalsBytes with deepEquals * blockchain/clique: address comments * blockchain/clique: ensure tests are ran --------- Co-authored-by: acolytec3 <17355484+acolytec3@users.noreply.github.com> --- packages/blockchain/src/consensus/clique.ts | 61 +- packages/blockchain/test/clique.spec.ts | 670 +++++++++++++------- packages/client/lib/miner/miner.ts | 13 +- 3 files changed, 509 insertions(+), 235 deletions(-) diff --git a/packages/blockchain/src/consensus/clique.ts b/packages/blockchain/src/consensus/clique.ts index b28760f788..b89aa64fc4 100644 --- a/packages/blockchain/src/consensus/clique.ts +++ b/packages/blockchain/src/consensus/clique.ts @@ -47,6 +47,10 @@ type CliqueLatestBlockSigners = CliqueBlockSigner[] /** * This class encapsulates Clique-related consensus functionality when used with the Blockchain class. + * Note: reorgs which happen between epoch transitions, which change the internal voting state over the reorg + * will result in failure and is currently not supported. + * The hotfix for this could be: re-load the latest epoch block (this has the clique state in the extraData of the header) + * Now replay all blocks on top of it. This should validate the chain up to the new/reorged tip which previously threw. */ export class CliqueConsensus implements Consensus { blockchain: Blockchain | undefined @@ -58,7 +62,7 @@ export class CliqueConsensus implements Consensus { * * This defines a limit for reorgs on PoA clique chains. */ - private CLIQUE_SIGNER_HISTORY_BLOCK_LIMIT = 100 + private CLIQUE_SIGNER_HISTORY_BLOCK_LIMIT = 200 /** * List with the latest signer states checkpointed on blocks where @@ -112,6 +116,7 @@ export class CliqueConsensus implements Consensus { async setup({ blockchain }: ConsensusOptions): Promise { this.blockchain = blockchain this._cliqueLatestSignerStates = await this.getCliqueLatestSignerStates() + this._cliqueLatestSignerStates.sort((a, b) => (a[0] > b[0] ? 1 : -1)) this._cliqueLatestVotes = await this.getCliqueLatestVotes() this._cliqueLatestBlockSigners = await this.getCliqueLatestBlockSigners() } @@ -126,7 +131,7 @@ export class CliqueConsensus implements Consensus { } const { header } = block - const valid = header.cliqueVerifySignature(this.cliqueActiveSigners()) + const valid = header.cliqueVerifySignature(this.cliqueActiveSigners(header.number)) if (!valid) { throw new Error('invalid PoA block signature (clique)') } @@ -140,7 +145,7 @@ export class CliqueConsensus implements Consensus { // only active (non-stale) votes will counted (if vote.blockNumber >= lastEpochBlockNumber const checkpointSigners = header.cliqueEpochTransitionSigners() - const activeSigners = this.cliqueActiveSigners() + const activeSigners = this.cliqueActiveSigners(header.number) for (const [i, cSigner] of checkpointSigners.entries()) { if (activeSigners[i]?.equals(cSigner) !== true) { throw new Error( @@ -161,7 +166,7 @@ export class CliqueConsensus implements Consensus { throw new Error(`${msg} ${header.errorStr()}`) } - const signers = this.cliqueActiveSigners() + const signers = this.cliqueActiveSigners(header.number) if (signers.length === 0) { // abort if signers are unavailable const msg = 'no signers available' @@ -215,7 +220,17 @@ export class CliqueConsensus implements Consensus { */ private async cliqueUpdateSignerStates(signerState?: CliqueSignerState) { if (signerState) { + const blockNumber = signerState[0] + const known = this._cliqueLatestSignerStates.find((value) => { + if (value[0] === blockNumber) { + return true + } + }) + if (known !== undefined) { + return + } this._cliqueLatestSignerStates.push(signerState) + this._cliqueLatestSignerStates.sort((a, b) => (a[0] > b[0] ? 1 : -1)) } // trim to CLIQUE_SIGNER_HISTORY_BLOCK_LIMIT @@ -240,10 +255,15 @@ export class CliqueConsensus implements Consensus { ]) await this.blockchain!.db.put(CLIQUE_SIGNERS_KEY, RLP.encode(formatted), DB_OPTS) // Output active signers for debugging purposes - let i = 0 - for (const signer of this.cliqueActiveSigners()) { - debug(`Clique signer [${i}]: ${signer}`) - i++ + if (signerState !== undefined) { + let i = 0 + try { + for (const signer of this.cliqueActiveSigners(signerState[0])) { + debug(`Clique signer [${i}]: ${signer} (block: ${signerState[0]})`) + i++ + } + // eslint-disable-next-line no-empty + } catch (e) {} } } @@ -268,8 +288,8 @@ export class CliqueConsensus implements Consensus { header.number - (header.number % BigInt((this.blockchain!._common.consensusConfig() as CliqueConfig).epoch)) - const limit = this.cliqueSignerLimit() - let activeSigners = this.cliqueActiveSigners() + const limit = this.cliqueSignerLimit(header.number) + let activeSigners = [...this.cliqueActiveSigners(header.number)] let consensus = false // AUTH vote analysis @@ -400,12 +420,17 @@ export class CliqueConsensus implements Consensus { /** * Returns a list with the current block signers */ - cliqueActiveSigners(): Address[] { + cliqueActiveSigners(blockNum: bigint): Address[] { const signers = this._cliqueLatestSignerStates if (signers.length === 0) { return [] } - return [...signers[signers.length - 1][1]] + for (let i = signers.length - 1; i >= 0; i--) { + if (signers[i][0] < blockNum) { + return signers[i][1] + } + } + throw new Error(`Could not load signers for block ${blockNum}`) } /** @@ -415,8 +440,8 @@ export class CliqueConsensus implements Consensus { * 1 -> 1, 2 -> 2, 3 -> 2, 4 -> 2, 5 -> 3, ... * @hidden */ - private cliqueSignerLimit() { - return Math.floor(this.cliqueActiveSigners().length / 2) + 1 + private cliqueSignerLimit(blockNum: bigint) { + return Math.floor(this.cliqueActiveSigners(blockNum).length / 2) + 1 } /** @@ -430,7 +455,7 @@ export class CliqueConsensus implements Consensus { // skip genesis, first block return false } - const limit = this.cliqueSignerLimit() + const limit = this.cliqueSignerLimit(header.number) // construct recent block signers list with this block let signers = this._cliqueLatestBlockSigners signers = signers.slice(signers.length < limit ? 0 : 1) @@ -484,7 +509,7 @@ export class CliqueConsensus implements Consensus { // trim length to `this.cliqueSignerLimit()` const length = this._cliqueLatestBlockSigners.length - const limit = this.cliqueSignerLimit() + const limit = this.cliqueSignerLimit(header.number) if (length > limit) { this._cliqueLatestBlockSigners = this._cliqueLatestBlockSigners.slice( length - limit, @@ -591,8 +616,8 @@ export class CliqueConsensus implements Consensus { * Helper to determine if a signer is in or out of turn for the next block. * @param signer The signer address */ - async cliqueSignerInTurn(signer: Address): Promise { - const signers = this.cliqueActiveSigners() + async cliqueSignerInTurn(signer: Address, blockNum: bigint): Promise { + const signers = this.cliqueActiveSigners(blockNum) const signerIndex = signers.findIndex((address) => address.equals(signer)) if (signerIndex === -1) { throw new Error('Signer not found') diff --git a/packages/blockchain/test/clique.spec.ts b/packages/blockchain/test/clique.spec.ts index 4cd8801f93..976a3366d7 100644 --- a/packages/blockchain/test/clique.spec.ts +++ b/packages/blockchain/test/clique.spec.ts @@ -10,161 +10,192 @@ import { CLIQUE_NONCE_AUTH, CLIQUE_NONCE_DROP } from '../src/consensus/clique' import type { CliqueConsensus } from '../src/consensus/clique' import type { CliqueConfig } from '@ethereumjs/common' +const COMMON = new Common({ chain: Chain.Rinkeby, hardfork: Hardfork.Chainstart }) +const EXTRA_DATA = new Uint8Array(97) +const GAS_LIMIT = BigInt(8000000) + +type Signer = { + address: Address + privateKey: Uint8Array + publicKey: Uint8Array +} + +const A: Signer = { + address: new Address(hexToBytes('0b90087d864e82a284dca15923f3776de6bb016f')), + privateKey: hexToBytes('64bf9cc30328b0e42387b3c82c614e6386259136235e20c1357bd11cdee86993'), + publicKey: hexToBytes( + '40b2ebdf4b53206d2d3d3d59e7e2f13b1ea68305aec71d5d24cefe7f24ecae886d241f9267f04702d7f693655eb7b4aa23f30dcd0c3c5f2b970aad7c8a828195' + ), +} + +const B: Signer = { + address: new Address(hexToBytes('6f62d8382bf2587361db73ceca28be91b2acb6df')), + privateKey: hexToBytes('2a6e9ad5a6a8e4f17149b8bc7128bf090566a11dbd63c30e5a0ee9f161309cd6'), + publicKey: hexToBytes( + 'ca0a55f6e81cb897aee6a1c390aa83435c41048faa0564b226cfc9f3df48b73e846377fb0fd606df073addc7bd851f22547afbbdd5c3b028c91399df802083a2' + ), +} + +const C: Signer = { + address: new Address(hexToBytes('83c30730d1972baa09765a1ac72a43db27fedce5')), + privateKey: hexToBytes('f216ddcf276079043c52b5dd144aa073e6b272ad4bfeaf4fbbc044aa478d1927'), + publicKey: hexToBytes( + '555b19a5cbe6dd082a4a1e1e0520dd52a82ba24fd5598ea31f0f31666c40905ed319314c5fb06d887b760229e1c0e616294e7b1cb5dfefb71507c9112132ce56' + ), +} + +const D: Signer = { + address: new Address(hexToBytes('8458f408106c4875c96679f3f556a511beabe138')), + privateKey: hexToBytes('159e95d07a6c64ddbafa6036cdb7b8114e6e8cdc449ca4b0468a6d0c955f991b'), + publicKey: hexToBytes( + 'f02724341e2df54cf53515f079b1354fa8d437e79c5b091b8d8cc7cbcca00fd8ad854cb3b3a85b06c44ecb7269404a67be88b561f2224c94d133e5fc21be915c' + ), +} + +const E: Signer = { + address: new Address(hexToBytes('ab80a948c661aa32d09952d2a6c4ad77a4c947be')), + privateKey: hexToBytes('48ec5a6c4a7fc67b10a9d4c8a8f594a81ae42e41ed061fa5218d96abb6012344'), + publicKey: hexToBytes( + 'adefb82b9f54e80aa3532263e4478739de16fcca6828f4ae842f8a07941c347fa59d2da1300569237009f0f122dc1fd6abb0db8fcb534280aa94948a5cc95f94' + ), +} + +const F: Signer = { + address: new Address(hexToBytes('dc7bc81ddf67d037d7439f8e6ff12f3d2a100f71')), + privateKey: hexToBytes('86b0ff7b6cf70786f29f297c57562905ab0b6c32d69e177a46491e56da9e486e'), + publicKey: hexToBytes( + 'd3e3d2b722e325bfc085ff5638a112b4e7e88ff13f92fc7f6cfc14b5a25e8d1545a2f27d8537b96e8919949d5f8c139ae7fc81aea7cf7fe5d43d7faaa038e35b' + ), +} + +const initWithSigners = async (signers: Signer[], common?: Common) => { + common = common ?? COMMON + const blocks: Block[] = [] + + const extraData = concatBytes( + new Uint8Array(32), + ...signers.map((s) => s.address.toBytes()), + new Uint8Array(65) + ) + const genesisBlock = Block.fromBlockData( + { header: { gasLimit: GAS_LIMIT, extraData } }, + { common } + ) + blocks.push(genesisBlock) + + const blockchain = await Blockchain.create({ + validateBlocks: true, + validateConsensus: true, + genesisBlock, + common, + }) + return { blocks, blockchain } +} + +function getBlock( + blockchain: Blockchain, + lastBlock: Block, + signer: Signer, + beneficiary?: [Signer, boolean], + checkpointSigners?: Signer[], + common?: Common +) { + common = common ?? COMMON + const number = lastBlock.header.number + BigInt(1) + + let coinbase = Address.zero() + let nonce = CLIQUE_NONCE_DROP + let extraData = EXTRA_DATA + if (beneficiary) { + coinbase = beneficiary[0].address + if (beneficiary[1]) { + nonce = CLIQUE_NONCE_AUTH + } + } else if (checkpointSigners) { + extraData = concatBytes( + new Uint8Array(32), + ...checkpointSigners.map((s) => s.address.toBytes()), + new Uint8Array(65) + ) + } + + const blockData = { + header: { + number, + parentHash: lastBlock.hash(), + coinbase, + timestamp: lastBlock.header.timestamp + BigInt(15), + extraData, + gasLimit: GAS_LIMIT, + difficulty: BigInt(2), + nonce, + }, + } + + // calculate difficulty + const signers = (blockchain.consensus as CliqueConsensus).cliqueActiveSigners(number) + const signerIndex = signers.findIndex((address: Address) => address.equals(signer.address)) + const inTurn = Number(number) % signers.length === signerIndex + blockData.header.difficulty = inTurn ? BigInt(2) : BigInt(1) + + // set signer + const cliqueSigner = signer.privateKey + + return Block.fromBlockData(blockData, { common, freeze: false, cliqueSigner }) +} + +const addNextBlockReorg = async ( + blockchain: Blockchain, + blocks: Block[], + forkBlock: Block, + signer: Signer, + beneficiary?: [Signer, boolean], + checkpointSigners?: Signer[], + common?: Common +) => { + const block = getBlock(blockchain, forkBlock, signer, beneficiary, checkpointSigners, common) + await blockchain.putBlock(block) + blocks.push(block) + return block +} + +const addNextBlock = async ( + blockchain: Blockchain, + blocks: Block[], + signer: Signer, + beneficiary?: [Signer, boolean], + checkpointSigners?: Signer[], + common?: Common +) => { + const block = getBlock( + blockchain, + blocks[blocks.length - 1], + signer, + beneficiary, + checkpointSigners, + common + ) + await blockchain.putBlock(block) + blocks.push(block) + return block +} + tape('Clique: Initialization', (t) => { t.test('should initialize a clique blockchain', async (st) => { const common = new Common({ chain: Chain.Rinkeby, hardfork: Hardfork.Chainstart }) const blockchain = await Blockchain.create({ common }) const head = await blockchain.getIteratorHead() - st.ok(equalsBytes(head.hash(), blockchain.genesisBlock.hash()), 'correct genesis hash') + st.deepEquals(head.hash(), blockchain.genesisBlock.hash(), 'correct genesis hash') st.deepEquals( - (blockchain.consensus as CliqueConsensus).cliqueActiveSigners(), + (blockchain.consensus as CliqueConsensus).cliqueActiveSigners(head.header.number + BigInt(1)), head.header.cliqueEpochTransitionSigners(), 'correct genesis signers' ) st.end() }) - const COMMON = new Common({ chain: Chain.Rinkeby, hardfork: Hardfork.Chainstart }) - const EXTRA_DATA = new Uint8Array(97) - const GAS_LIMIT = BigInt(8000000) - - type Signer = { - address: Address - privateKey: Uint8Array - publicKey: Uint8Array - } - - const A: Signer = { - address: new Address(hexToBytes('0b90087d864e82a284dca15923f3776de6bb016f')), - privateKey: hexToBytes('64bf9cc30328b0e42387b3c82c614e6386259136235e20c1357bd11cdee86993'), - publicKey: hexToBytes( - '40b2ebdf4b53206d2d3d3d59e7e2f13b1ea68305aec71d5d24cefe7f24ecae886d241f9267f04702d7f693655eb7b4aa23f30dcd0c3c5f2b970aad7c8a828195' - ), - } - - const B: Signer = { - address: new Address(hexToBytes('6f62d8382bf2587361db73ceca28be91b2acb6df')), - privateKey: hexToBytes('2a6e9ad5a6a8e4f17149b8bc7128bf090566a11dbd63c30e5a0ee9f161309cd6'), - publicKey: hexToBytes( - 'ca0a55f6e81cb897aee6a1c390aa83435c41048faa0564b226cfc9f3df48b73e846377fb0fd606df073addc7bd851f22547afbbdd5c3b028c91399df802083a2' - ), - } - - const C: Signer = { - address: new Address(hexToBytes('83c30730d1972baa09765a1ac72a43db27fedce5')), - privateKey: hexToBytes('f216ddcf276079043c52b5dd144aa073e6b272ad4bfeaf4fbbc044aa478d1927'), - publicKey: hexToBytes( - '555b19a5cbe6dd082a4a1e1e0520dd52a82ba24fd5598ea31f0f31666c40905ed319314c5fb06d887b760229e1c0e616294e7b1cb5dfefb71507c9112132ce56' - ), - } - - const D: Signer = { - address: new Address(hexToBytes('8458f408106c4875c96679f3f556a511beabe138')), - privateKey: hexToBytes('159e95d07a6c64ddbafa6036cdb7b8114e6e8cdc449ca4b0468a6d0c955f991b'), - publicKey: hexToBytes( - 'f02724341e2df54cf53515f079b1354fa8d437e79c5b091b8d8cc7cbcca00fd8ad854cb3b3a85b06c44ecb7269404a67be88b561f2224c94d133e5fc21be915c' - ), - } - - const E: Signer = { - address: new Address(hexToBytes('ab80a948c661aa32d09952d2a6c4ad77a4c947be')), - privateKey: hexToBytes('48ec5a6c4a7fc67b10a9d4c8a8f594a81ae42e41ed061fa5218d96abb6012344'), - publicKey: hexToBytes( - 'adefb82b9f54e80aa3532263e4478739de16fcca6828f4ae842f8a07941c347fa59d2da1300569237009f0f122dc1fd6abb0db8fcb534280aa94948a5cc95f94' - ), - } - - const F: Signer = { - address: new Address(hexToBytes('dc7bc81ddf67d037d7439f8e6ff12f3d2a100f71')), - privateKey: hexToBytes('86b0ff7b6cf70786f29f297c57562905ab0b6c32d69e177a46491e56da9e486e'), - publicKey: hexToBytes( - 'd3e3d2b722e325bfc085ff5638a112b4e7e88ff13f92fc7f6cfc14b5a25e8d1545a2f27d8537b96e8919949d5f8c139ae7fc81aea7cf7fe5d43d7faaa038e35b' - ), - } - - const initWithSigners = async (signers: Signer[], common?: Common) => { - common = common ?? COMMON - const blocks: Block[] = [] - - const extraData = concatBytes( - new Uint8Array(32), - ...signers.map((s) => s.address.toBytes()), - new Uint8Array(65) - ) - const genesisBlock = Block.fromBlockData( - { header: { gasLimit: GAS_LIMIT, extraData } }, - { common } - ) - blocks.push(genesisBlock) - - const blockchain = await Blockchain.create({ - validateBlocks: true, - validateConsensus: true, - genesisBlock, - common, - }) - return { blocks, blockchain } - } - - const addNextBlock = async ( - blockchain: Blockchain, - blocks: Block[], - signer: Signer, - beneficiary?: [Signer, boolean], - checkpointSigners?: Signer[], - common?: Common - ) => { - common = common ?? COMMON - const number = blocks.length - const lastBlock = blocks[number - 1] - - let coinbase = Address.zero() - let nonce = CLIQUE_NONCE_DROP - let extraData = EXTRA_DATA - if (beneficiary) { - coinbase = beneficiary[0].address - if (beneficiary[1]) { - nonce = CLIQUE_NONCE_AUTH - } - } else if (checkpointSigners) { - extraData = concatBytes( - new Uint8Array(32), - ...checkpointSigners.map((s) => s.address.toBytes()), - new Uint8Array(65) - ) - } - - const blockData = { - header: { - number, - parentHash: lastBlock.hash(), - coinbase, - timestamp: lastBlock.header.timestamp + BigInt(15), - extraData, - gasLimit: GAS_LIMIT, - difficulty: BigInt(2), - nonce, - }, - } - - // calculate difficulty - const signers = (blockchain.consensus as CliqueConsensus).cliqueActiveSigners() - const signerIndex = signers.findIndex((address: Address) => address.equals(signer.address)) - const inTurn = number % signers.length === signerIndex - blockData.header.difficulty = inTurn ? BigInt(2) : BigInt(1) - - // set signer - const cliqueSigner = signer.privateKey - - const block = Block.fromBlockData(blockData, { common, freeze: false, cliqueSigner }) - - await blockchain.putBlock(block) - blocks.push(block) - return block - } - t.test('should throw if signer in epoch checkpoint is not active', async (st) => { const { blockchain } = await initWithSigners([A]) ;(blockchain as any)._validateBlocks = false @@ -282,7 +313,12 @@ tape('Clique: Initialization', (t) => { const { blocks, blockchain } = await initWithSigners([A]) const block = await addNextBlock(blockchain, blocks, A) st.equal(block.header.number, BigInt(1)) - st.deepEqual((blockchain.consensus as CliqueConsensus).cliqueActiveSigners(), [A.address]) + st.deepEqual( + (blockchain.consensus as CliqueConsensus).cliqueActiveSigners( + block.header.number + BigInt(1) + ), + [A.address] + ) st.end() }) @@ -292,7 +328,9 @@ tape('Clique: Initialization', (t) => { await addNextBlock(blockchain, blocks, B) await addNextBlock(blockchain, blocks, A, [C, true]) st.deepEqual( - (blockchain.consensus as CliqueConsensus).cliqueActiveSigners(), + (blockchain.consensus as CliqueConsensus).cliqueActiveSigners( + blocks[blocks.length - 1].header.number + BigInt(1) + ), [A.address, B.address], 'only accept first, second needs 2 votes' ) @@ -310,19 +348,40 @@ tape('Clique: Initialization', (t) => { await addNextBlock(blockchain, blocks, B, [E, true]) st.deepEqual( - (blockchain.consensus as CliqueConsensus).cliqueActiveSigners(), + (blockchain.consensus as CliqueConsensus).cliqueActiveSigners( + blocks[blocks.length - 1].header.number + BigInt(1) + ), [A.address, B.address, C.address, D.address], 'only accept first two, third needs 3 votes already' ) st.end() }) + t.test('Ensure old clique states are remembered', async (st) => { + const { blocks, blockchain } = await initWithSigners([A, B]) + await addNextBlock(blockchain, blocks, A, [C, true]) + await addNextBlock(blockchain, blocks, B, [C, true]) + await addNextBlock(blockchain, blocks, A, [D, true]) + await addNextBlock(blockchain, blocks, B, [D, true]) + await addNextBlock(blockchain, blocks, C) + await addNextBlock(blockchain, blocks, A, [E, true]) + await addNextBlock(blockchain, blocks, B, [E, true]) + await addNextBlock(blockchain, blocks, C) + + for (let i = 1; i < blocks.length; i++) { + await blockchain.putBlock(blocks[i]) + } + st.end() + }) + t.test('Clique Voting: Single signer, dropping itself)', async (st) => { const { blocks, blockchain } = await initWithSigners([A]) await addNextBlock(blockchain, blocks, A, [A, false]) st.deepEqual( - (blockchain.consensus as CliqueConsensus).cliqueActiveSigners(), + (blockchain.consensus as CliqueConsensus).cliqueActiveSigners( + blocks[blocks.length - 1].header.number + BigInt(1) + ), [], 'weird, but one less cornercase by explicitly allowing this' ) @@ -336,7 +395,9 @@ tape('Clique: Initialization', (t) => { await addNextBlock(blockchain, blocks, A, [B, false]) st.deepEqual( - (blockchain.consensus as CliqueConsensus).cliqueActiveSigners(), + (blockchain.consensus as CliqueConsensus).cliqueActiveSigners( + blocks[blocks.length - 1].header.number + BigInt(1) + ), [A.address, B.address], 'not fulfilled' ) @@ -352,7 +413,9 @@ tape('Clique: Initialization', (t) => { await addNextBlock(blockchain, blocks, B, [B, false]) st.deepEqual( - (blockchain.consensus as CliqueConsensus).cliqueActiveSigners(), + (blockchain.consensus as CliqueConsensus).cliqueActiveSigners( + blocks[blocks.length - 1].header.number + BigInt(1) + ), [A.address], 'fulfilled' ) @@ -365,10 +428,12 @@ tape('Clique: Initialization', (t) => { await addNextBlock(blockchain, blocks, A, [C, false]) await addNextBlock(blockchain, blocks, B, [C, false]) - st.deepEqual((blockchain.consensus as CliqueConsensus).cliqueActiveSigners(), [ - A.address, - B.address, - ]) + st.deepEqual( + (blockchain.consensus as CliqueConsensus).cliqueActiveSigners( + blocks[blocks.length - 1].header.number + BigInt(1) + ), + [A.address, B.address] + ) st.end() }) @@ -379,12 +444,12 @@ tape('Clique: Initialization', (t) => { await addNextBlock(blockchain, blocks, A, [C, false]) await addNextBlock(blockchain, blocks, B, [C, false]) - st.deepEqual((blockchain.consensus as CliqueConsensus).cliqueActiveSigners(), [ - A.address, - B.address, - C.address, - D.address, - ]) + st.deepEqual( + (blockchain.consensus as CliqueConsensus).cliqueActiveSigners( + blocks[blocks.length - 1].header.number + BigInt(1) + ), + [A.address, B.address, C.address, D.address] + ) st.end() } ) @@ -397,11 +462,12 @@ tape('Clique: Initialization', (t) => { await addNextBlock(blockchain, blocks, B, [D, false]) await addNextBlock(blockchain, blocks, C, [D, false]) - st.deepEqual((blockchain.consensus as CliqueConsensus).cliqueActiveSigners(), [ - A.address, - B.address, - C.address, - ]) + st.deepEqual( + (blockchain.consensus as CliqueConsensus).cliqueActiveSigners( + blocks[blocks.length - 1].header.number + BigInt(1) + ), + [A.address, B.address, C.address] + ) st.end() } ) @@ -414,10 +480,12 @@ tape('Clique: Initialization', (t) => { await addNextBlock(blockchain, blocks, B) await addNextBlock(blockchain, blocks, A, [C, true]) - st.deepEqual((blockchain.consensus as CliqueConsensus).cliqueActiveSigners(), [ - A.address, - B.address, - ]) + st.deepEqual( + (blockchain.consensus as CliqueConsensus).cliqueActiveSigners( + blocks[blocks.length - 1].header.number + BigInt(1) + ), + [A.address, B.address] + ) st.end() }) @@ -432,12 +500,12 @@ tape('Clique: Initialization', (t) => { await addNextBlock(blockchain, blocks, A) await addNextBlock(blockchain, blocks, B, [C, true]) - st.deepEqual((blockchain.consensus as CliqueConsensus).cliqueActiveSigners(), [ - A.address, - B.address, - C.address, - D.address, - ]) + st.deepEqual( + (blockchain.consensus as CliqueConsensus).cliqueActiveSigners( + blocks[blocks.length - 1].header.number + BigInt(1) + ), + [A.address, B.address, C.address, D.address] + ) st.end() }) @@ -449,10 +517,12 @@ tape('Clique: Initialization', (t) => { await addNextBlock(blockchain, blocks, B) await addNextBlock(blockchain, blocks, A, [B, false]) - st.deepEqual((blockchain.consensus as CliqueConsensus).cliqueActiveSigners(), [ - A.address, - B.address, - ]) + st.deepEqual( + (blockchain.consensus as CliqueConsensus).cliqueActiveSigners( + blocks[blocks.length - 1].header.number + BigInt(1) + ), + [A.address, B.address] + ) st.end() }) @@ -470,10 +540,12 @@ tape('Clique: Initialization', (t) => { await addNextBlock(blockchain, blocks, A) await addNextBlock(blockchain, blocks, B, [C, false]) - st.deepEqual((blockchain.consensus as CliqueConsensus).cliqueActiveSigners(), [ - A.address, - B.address, - ]) + st.deepEqual( + (blockchain.consensus as CliqueConsensus).cliqueActiveSigners( + blocks[blocks.length - 1].header.number + BigInt(1) + ), + [A.address, B.address] + ) st.end() }) @@ -485,7 +557,9 @@ tape('Clique: Initialization', (t) => { await addNextBlock(blockchain, blocks, A, [B, false]) st.deepEqual( - (blockchain.consensus as CliqueConsensus).cliqueActiveSigners(), + (blockchain.consensus as CliqueConsensus).cliqueActiveSigners( + blocks[blocks.length - 1].header.number + BigInt(1) + ), [A.address, B.address], 'deauth votes' ) @@ -500,7 +574,9 @@ tape('Clique: Initialization', (t) => { await addNextBlock(blockchain, blocks, A, [D, true]) st.deepEqual( - (blockchain.consensus as CliqueConsensus).cliqueActiveSigners(), + (blockchain.consensus as CliqueConsensus).cliqueActiveSigners( + blocks[blocks.length - 1].header.number + BigInt(1) + ), [A.address, B.address], 'auth votes' ) @@ -523,10 +599,12 @@ tape('Clique: Initialization', (t) => { await addNextBlock(blockchain, blocks, A) await addNextBlock(blockchain, blocks, C, [C, true]) - st.deepEqual((blockchain.consensus as CliqueConsensus).cliqueActiveSigners(), [ - A.address, - B.address, - ]) + st.deepEqual( + (blockchain.consensus as CliqueConsensus).cliqueActiveSigners( + blocks[blocks.length - 1].header.number + BigInt(1) + ), + [A.address, B.address] + ) st.end() } ) @@ -547,11 +625,12 @@ tape('Clique: Initialization', (t) => { await addNextBlock(blockchain, blocks, A) await addNextBlock(blockchain, blocks, B, [C, true]) - st.deepEqual((blockchain.consensus as CliqueConsensus).cliqueActiveSigners(), [ - A.address, - B.address, - C.address, - ]) + st.deepEqual( + (blockchain.consensus as CliqueConsensus).cliqueActiveSigners( + blocks[blocks.length - 1].header.number + BigInt(1) + ), + [A.address, B.address, C.address] + ) st.end() } ) @@ -578,13 +657,12 @@ tape('Clique: Initialization', (t) => { await addNextBlock(blockchain, blocks, D, [A, false]) await addNextBlock(blockchain, blocks, B, [F, true]) // Finish authorizing F, 3/3 votes needed - st.deepEqual((blockchain.consensus as CliqueConsensus).cliqueActiveSigners(), [ - B.address, - C.address, - D.address, - E.address, - F.address, - ]) + st.deepEqual( + (blockchain.consensus as CliqueConsensus).cliqueActiveSigners( + blocks[blocks.length - 1].header.number + BigInt(1) + ), + [B.address, C.address, D.address, E.address, F.address] + ) st.end() } ) @@ -614,10 +692,12 @@ tape('Clique: Initialization', (t) => { await addNextBlock(blockchain, blocks, A, undefined, [A, B], common) await addNextBlock(blockchain, blocks, B, [C, true], undefined, common) - st.deepEqual((blockchain.consensus as CliqueConsensus).cliqueActiveSigners(), [ - A.address, - B.address, - ]) + st.deepEqual( + (blockchain.consensus as CliqueConsensus).cliqueActiveSigners( + blocks[blocks.length - 1].header.number + BigInt(1) + ), + [A.address, B.address] + ) st.end() } ) @@ -698,24 +778,186 @@ tape('Clique: Initialization', (t) => { const { blocks, blockchain } = await initWithSigners([A, B, C]) // block 1: B, next signer: C await addNextBlock(blockchain, blocks, B) - st.notOk(await (blockchain.consensus as CliqueConsensus).cliqueSignerInTurn(A.address)) - st.notOk(await (blockchain.consensus as CliqueConsensus).cliqueSignerInTurn(B.address)) - st.ok(await (blockchain.consensus as CliqueConsensus).cliqueSignerInTurn(C.address)) + st.notOk( + await (blockchain.consensus as CliqueConsensus).cliqueSignerInTurn( + A.address, + blocks[blocks.length - 1].header.number + ) + ) + st.notOk( + await (blockchain.consensus as CliqueConsensus).cliqueSignerInTurn( + B.address, + blocks[blocks.length - 1].header.number + ) + ) + st.ok( + await (blockchain.consensus as CliqueConsensus).cliqueSignerInTurn( + C.address, + blocks[blocks.length - 1].header.number + ) + ) // block 2: C, next signer: A await addNextBlock(blockchain, blocks, C) - st.ok(await (blockchain.consensus as CliqueConsensus).cliqueSignerInTurn(A.address)) - st.notOk(await (blockchain.consensus as CliqueConsensus).cliqueSignerInTurn(B.address)) - st.notOk(await (blockchain.consensus as CliqueConsensus).cliqueSignerInTurn(C.address)) + st.ok( + await (blockchain.consensus as CliqueConsensus).cliqueSignerInTurn( + A.address, + blocks[blocks.length - 1].header.number + ) + ) + st.notOk( + await (blockchain.consensus as CliqueConsensus).cliqueSignerInTurn( + B.address, + blocks[blocks.length - 1].header.number + ) + ) + st.notOk( + await (blockchain.consensus as CliqueConsensus).cliqueSignerInTurn( + C.address, + blocks[blocks.length - 1].header.number + ) + ) // block 3: A, next signer: B await addNextBlock(blockchain, blocks, A) - st.notOk(await (blockchain.consensus as CliqueConsensus).cliqueSignerInTurn(A.address)) - st.ok(await (blockchain.consensus as CliqueConsensus).cliqueSignerInTurn(B.address)) - st.notOk(await (blockchain.consensus as CliqueConsensus).cliqueSignerInTurn(C.address)) + st.notOk( + await (blockchain.consensus as CliqueConsensus).cliqueSignerInTurn( + A.address, + blocks[blocks.length - 1].header.number + ) + ) + st.ok( + await (blockchain.consensus as CliqueConsensus).cliqueSignerInTurn( + B.address, + blocks[blocks.length - 1].header.number + ) + ) + st.notOk( + await (blockchain.consensus as CliqueConsensus).cliqueSignerInTurn( + C.address, + blocks[blocks.length - 1].header.number + ) + ) // block 4: B, next signer: C await addNextBlock(blockchain, blocks, B) - st.notOk(await (blockchain.consensus as CliqueConsensus).cliqueSignerInTurn(A.address)) - st.notOk(await (blockchain.consensus as CliqueConsensus).cliqueSignerInTurn(B.address)) - st.ok(await (blockchain.consensus as CliqueConsensus).cliqueSignerInTurn(C.address)) + st.notOk( + await (blockchain.consensus as CliqueConsensus).cliqueSignerInTurn( + A.address, + blocks[blocks.length - 1].header.number + ) + ) + st.notOk( + await (blockchain.consensus as CliqueConsensus).cliqueSignerInTurn( + B.address, + blocks[blocks.length - 1].header.number + ) + ) + st.ok( + await (blockchain.consensus as CliqueConsensus).cliqueSignerInTurn( + C.address, + blocks[blocks.length - 1].header.number + ) + ) st.end() }) }) + +tape('clique: reorgs', (t) => { + t.test( + 'Two signers, voting to add one other signer, then reorg and revoke this addition', + async (st) => { + const { blocks, blockchain } = await initWithSigners([A, B]) + const genesis = blocks[0] + await addNextBlock(blockchain, blocks, A, [C, true]) + const headBlockUnforked = await addNextBlock(blockchain, blocks, B, [C, true]) + st.deepEqual( + (blockchain.consensus as CliqueConsensus).cliqueActiveSigners( + blocks[blocks.length - 1].header.number + BigInt(1) + ), + [A.address, B.address, C.address], + 'address C added to signers' + ) + st.deepEquals((await blockchain.getCanonicalHeadBlock()).hash(), headBlockUnforked.hash()) + await addNextBlockReorg(blockchain, blocks, genesis, B) + const headBlock = await addNextBlock(blockchain, blocks, A) + st.deepEquals((await blockchain.getCanonicalHeadBlock()).hash(), headBlock.hash()) + await addNextBlock(blockchain, blocks, B) + await addNextBlock(blockchain, blocks, A) + + st.deepEqual( + (blockchain.consensus as CliqueConsensus).cliqueActiveSigners( + blocks[blocks.length - 1].header.number + BigInt(1) + ), + [A.address, B.address], + 'address C not added to signers' + ) + + st.end() + } + ) + + /** + * This test fails, but demonstrates why at an epoch reorg with changing votes, we get an internal error. + t.test( + 'Two signers, voting to add one other signer, epoch transition, then reorg and revoke this addition', + async (st) => { + const common = Common.custom( + { + consensus: { + type: ConsensusType.ProofOfAuthority, + algorithm: ConsensusAlgorithm.Clique, + clique: { + period: 15, + epoch: 3, + }, + }, + }, + { + baseChain: Chain.Rinkeby, + hardfork: Hardfork.Chainstart, + } + ) + const { blocks, blockchain } = await initWithSigners([A, B]) + const genesis = blocks[0] + await addNextBlock(blockchain, blocks, A, [C, true], undefined, common) + await addNextBlock(blockchain, blocks, B, [C, true], undefined, common) + await addNextBlock(blockchain, blocks, A, undefined, undefined, common) + const headBlockUnforked = await addNextBlock( + blockchain, + blocks, + B, + undefined, + undefined, + common + ) + st.deepEqual( + (blockchain.consensus as CliqueConsensus).cliqueActiveSigners( + blocks[blocks.length - 1].header.number + BigInt(1) + ), + [A.address, B.address, C.address], + 'address C added to signers' + ) + st.deepEquals((await blockchain.getCanonicalHeadBlock()).hash(), headBlockUnforked.hash()) + await addNextBlockReorg(blockchain, blocks, genesis, B, undefined, undefined, common) + await addNextBlock(blockchain, blocks, A, undefined, undefined, common) + + // Add block 3: epoch transition + await addNextBlock(blockchain, blocks, B, undefined, undefined, common) + // Now here suddenly C is added again as signer + + await addNextBlock(blockchain, blocks, A, undefined, undefined, common) + await addNextBlock(blockchain, blocks, B, undefined, undefined, common) + + const headBlock = await addNextBlock(blockchain, blocks, A, undefined, undefined, common) + st.deepEquals((await blockchain.getCanonicalHeadBlock()).hash(), headBlock.hash()) + + st.deepEqual( + (blockchain.consensus as CliqueConsensus).cliqueActiveSigners( + blocks[blocks.length - 1].header.number + BigInt(1) + ), + [A.address, B.address], + 'address C not added to signers' + ) + + st.end() + } + ) */ +}) diff --git a/packages/client/lib/miner/miner.ts b/packages/client/lib/miner/miner.ts index ad4ee93637..edb66401d9 100644 --- a/packages/client/lib/miner/miner.ts +++ b/packages/client/lib/miner/miner.ts @@ -106,11 +106,17 @@ export class Miner { // delay signing by rand(SIGNER_COUNT * 500ms) const [signerAddress] = this.config.accounts[0] const { blockchain } = this.service.chain + const parentBlock = this.service.chain.blocks.latest! + //eslint-disable-next-line + const number = parentBlock.header.number + BigInt(1) const inTurn = await (blockchain.consensus as CliqueConsensus).cliqueSignerInTurn( - signerAddress + signerAddress, + number ) if (inTurn === false) { - const signerCount = (blockchain.consensus as CliqueConsensus).cliqueActiveSigners().length + const signerCount = (blockchain.consensus as CliqueConsensus).cliqueActiveSigners( + number + ).length timeout += Math.random() * signerCount * 500 } } @@ -241,7 +247,8 @@ export class Miner { cliqueSigner = signerPrivKey // Determine if signer is INTURN (2) or NOTURN (1) inTurn = await (vmCopy.blockchain.consensus as CliqueConsensus).cliqueSignerInTurn( - signerAddress + signerAddress, + number ) difficulty = inTurn ? 2 : 1 } From 133d3f6b3b6ec67e3093ad94bed31e0b80984081 Mon Sep 17 00:00:00 2001 From: Jochem Brouwer Date: Tue, 11 Apr 2023 01:55:11 +0200 Subject: [PATCH 04/53] Fix `pyspec` hive tests (#2621) * client: update engine-only rpc methods to be exposed by spec * common: add support for geth configs with gasLimit/difficulty > Number.MAX_SAFE_INTEGER * client: ensure if private key is unlocked, remove any accidentally added newlines from file [no ci] * blockchain: support genesis nonce [no ci] * vm/eei: also read nonce from genesis [no ci] * vm/eei: ensure empty accounts at genesis are not marked as touched [no ci] * trie: ensure checkRoot returns true in case root of empty trie is provided * vm: fix tests --------- Co-authored-by: acolytec3 <17355484+acolytec3@users.noreply.github.com> --- packages/blockchain/src/genesisStates/index.ts | 11 ++++++++--- packages/blockchain/src/utils.ts | 5 +++-- packages/client/bin/cli.ts | 2 +- packages/client/lib/util/rpc.ts | 7 +++---- packages/common/src/types.ts | 4 ++-- packages/common/src/utils.ts | 4 ++-- packages/trie/src/trie/trie.ts | 2 +- packages/vm/src/eei/vmState.ts | 6 ++++-- packages/vm/test/api/customChain.spec.ts | 1 + 9 files changed, 25 insertions(+), 17 deletions(-) diff --git a/packages/blockchain/src/genesisStates/index.ts b/packages/blockchain/src/genesisStates/index.ts index 838daf9fd0..db59759065 100644 --- a/packages/blockchain/src/genesisStates/index.ts +++ b/packages/blockchain/src/genesisStates/index.ts @@ -11,7 +11,8 @@ export type StoragePair = [key: PrefixedHexString, value: PrefixedHexString] export type AccountState = [ balance: PrefixedHexString, code: PrefixedHexString, - storage: Array + storage: Array, + nonce: PrefixedHexString ] export interface GenesisState { @@ -29,12 +30,13 @@ export async function genesisStateRoot(genesisState: GenesisState) { if (typeof value === 'string') { account.balance = BigInt(value) } else { - const [balance, code, storage] = value as Partial + const [balance, code, storage, nonce] = value as Partial if (balance !== undefined) { account.balance = BigInt(balance) } if (code !== undefined) { - account.codeHash = keccak256(toBytes(code)) + const codeBytes = isHexPrefixed(code) ? toBytes(code) : hexToBytes(code) + account.codeHash = keccak256(codeBytes) } if (storage !== undefined) { const storageTrie = new Trie({ useKeyHashing: true }) @@ -47,6 +49,9 @@ export async function genesisStateRoot(genesisState: GenesisState) { } account.storageRoot = storageTrie.root() } + if (nonce !== undefined) { + account.nonce = BigInt(nonce) + } } await trie.put(address, account.serialize()) } diff --git a/packages/blockchain/src/utils.ts b/packages/blockchain/src/utils.ts index d78953eb15..eba8d07ded 100644 --- a/packages/blockchain/src/utils.ts +++ b/packages/blockchain/src/utils.ts @@ -9,12 +9,13 @@ import type { GenesisState } from './genesisStates' export function parseGethGenesisState(json: any) { const state: GenesisState = {} for (let address of Object.keys(json.alloc)) { - let { balance, code, storage } = json.alloc[address] + let { balance, code, storage, nonce } = json.alloc[address] address = addHexPrefix(address) balance = isHexPrefixed(balance) ? balance : bigIntToHex(BigInt(balance)) code = code !== undefined ? addHexPrefix(code) : undefined storage = storage !== undefined ? Object.entries(storage) : undefined - state[address] = [balance, code, storage] as any + nonce = nonce !== undefined ? addHexPrefix(nonce) : undefined + state[address] = [balance, code, storage, nonce] as any } return state } diff --git a/packages/client/bin/cli.ts b/packages/client/bin/cli.ts index 54ba708795..11c243224e 100755 --- a/packages/client/bin/cli.ts +++ b/packages/client/bin/cli.ts @@ -593,7 +593,7 @@ async function inputAccounts() { } } } else { - const acc = readFileSync(path.resolve(args.unlock!), 'utf-8') + const acc = readFileSync(path.resolve(args.unlock!), 'utf-8').replace(/(\r\n|\n|\r)/gm, '') const privKey = hexStringToBytes(acc) const derivedAddress = Address.fromPrivateKey(privKey) accounts.push([derivedAddress, privKey]) diff --git a/packages/client/lib/util/rpc.ts b/packages/client/lib/util/rpc.ts index 54216b8c9b..7694df9f09 100644 --- a/packages/client/lib/util/rpc.ts +++ b/packages/client/lib/util/rpc.ts @@ -117,8 +117,9 @@ export function createRPCServer( break case MethodConfig.EngineOnly: { /** - * Filter eth methods to be exposed with engine as per kiln spec 2.1 - * From: https://github.com/ethereum/execution-apis/blob/v1.0.0-alpha.8/src/engine/specification.md#underlying-protocol + * Filter eth methods which should be strictly exposed if only the engine is started: + * https://github.com/ethereum/execution-apis/blob/6d2c035e4caafef7224cbb5fac7993b820bb61ce/src/engine/common.md#underlying-protocol + * (Feb 3 2023) */ const ethMethodsToBeIncluded = [ 'eth_blockNumber', @@ -130,8 +131,6 @@ export function createRPCServer( 'eth_getLogs', 'eth_sendRawTransaction', 'eth_syncing', - 'eth_getTransactionCount', - 'eth_getTransactionReceipt', ] const ethEngineSubsetMethods: { [key: string]: Function } = {} for (const method of ethMethodsToBeIncluded) { diff --git a/packages/common/src/types.ts b/packages/common/src/types.ts index a3e5e437bc..c5b9b46c6f 100644 --- a/packages/common/src/types.ts +++ b/packages/common/src/types.ts @@ -37,8 +37,8 @@ export interface ChainConfig { export interface GenesisBlockConfig { timestamp?: string - gasLimit: number - difficulty: number + gasLimit: number | string + difficulty: number | string nonce: string extraData: string baseFeePerGas?: string diff --git a/packages/common/src/utils.ts b/packages/common/src/utils.ts index 5939506f81..e427b731de 100644 --- a/packages/common/src/utils.ts +++ b/packages/common/src/utils.ts @@ -78,8 +78,8 @@ function parseGethParams(json: any, mergeForkIdPostMerge: boolean = true) { networkId: chainId, genesis: { timestamp, - gasLimit: parseInt(gasLimit), // geth gasLimit and difficulty are hex strings while ours are `number`s - difficulty: parseInt(difficulty), + gasLimit, + difficulty, nonce, extraData, mixHash, diff --git a/packages/trie/src/trie/trie.ts b/packages/trie/src/trie/trie.ts index dafa5b6159..19e5fd4d33 100644 --- a/packages/trie/src/trie/trie.ts +++ b/packages/trie/src/trie/trie.ts @@ -130,7 +130,7 @@ export class Trie { return value !== null } catch (error: any) { if (error.message === 'Missing node in DB') { - return false + return equalsBytes(root, this.EMPTY_TRIE_ROOT) } else { throw error } diff --git a/packages/vm/src/eei/vmState.ts b/packages/vm/src/eei/vmState.ts index 98cbadf9e2..48c2c40ac8 100644 --- a/packages/vm/src/eei/vmState.ts +++ b/packages/vm/src/eei/vmState.ts @@ -252,8 +252,8 @@ export class VmState implements EVMStateAccess { await this.putAccount(addr, account) } else { // New format: address -> [balance, code, storage] - const [balance, code, storage] = state - const account = Account.fromAccountData({ balance }) + const [balance, code, storage, nonce] = state + const account = Account.fromAccountData({ balance, nonce }) await this.putAccount(addr, account) if (code !== undefined) { await this.putContractCode(addr, toBytes(code)) @@ -266,6 +266,8 @@ export class VmState implements EVMStateAccess { } } await this._stateManager.flush() + // If any empty accounts are put, these should not be marked as touched (when first tx is ran, this account is deleted when it cleans up the accounts) + this.touchedJournal.clear() } /** diff --git a/packages/vm/test/api/customChain.spec.ts b/packages/vm/test/api/customChain.spec.ts index f95a689a96..3456113b6f 100644 --- a/packages/vm/test/api/customChain.spec.ts +++ b/packages/vm/test/api/customChain.spec.ts @@ -24,6 +24,7 @@ const accountState: AccountState = [ '0x0', '0x6080604052348015600f57600080fd5b506004361060285760003560e01c80632e64cec114602d575b600080fd5b60336047565b604051603e9190605d565b60405180910390f35b60008054905090565b6057816076565b82525050565b6000602082019050607060008301846050565b92915050565b600081905091905056fea2646970667358221220338001095242a334ada78025237955fa36b6f2f895ea7f297b69af72f8bc7fd164736f6c63430008070033', storage, + '0x0', ] /** From fb400f712a23766d5afa16a920cd02bfc0913859 Mon Sep 17 00:00:00 2001 From: g11tech Date: Tue, 11 Apr 2023 21:41:34 +0530 Subject: [PATCH 05/53] 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 From 8fcf707d8aa8dc6f9d6032b60ffd317052ad0c5f Mon Sep 17 00:00:00 2001 From: Holger Drewes Date: Thu, 13 Apr 2023 09:19:15 +0200 Subject: [PATCH 06/53] Statemanager: Cache Rewrite (Account/Storage) & Refactoring (Interface/Tests) (#2630) * StateManager: Account/Storage cache rewrite, API & Test Refactoring StateManager: added deactivateCache flag, adopted and expanded tests Client/StateManager: use cacheless SM in client, fix StateManager.copy() not taking options into account StateManager: reworked cache, access and diff cache separation (WIP) StateManager: continued cache reworking StateManager -> Cache: logic fix in commit() Util: added storageRoot KECCAK256_RLP comparison for Account.isEmpty() StateManager: Cache logic fixes, explicit checkpointing test suite StateManager/VM: fixed VM API tests (account exists) Lint fix StateManager -> Cache: Added cache clearing logic and options, added tests StateManager/EVM/VM: added cache clearing options Client: state cache integration, statistics output StateManager -> Cache: In-cache vs virtual improvements StateManager -> Cache: Refactor/rewrite with clear account-in-cache/account-exists differentiation, return undefined in SM for not existing accounts, throw early for unintended non-account accesses StateManager/EVM/VM: continues fixes, additional no-account exceptions (WIP) Continued fixes Continued fixes Lessen account restriction (early throws) on first round (too many test failures) Continued fixes and first-round loosening of restrictions Continued fixes EVM fix Client: significantly increase state cache threshold from 500 to 25000 blocks VM: fix DAO state changes not being committed early enough to disk (and taken in for new state root) due to new diff-based cache structure StateManager: added very simple code cache VM/EVM test and example fixes Util: revert storageRoot check in Account.isEmpty() EVM: fix EXTCODEHASH bug vm: fix example [no ci] vm: ensure touched accounts are cleared after generating genesis client: lint StateManager: use lru-cache package for cache (WIP) StateManager/EVM/VM/Client: remove threshold logic, simplify cache clearing StateManager, Client: add size as new StateManager/Cache option Client: added missing cache stats output StateManager: downgrade lru-cache dependency from v8 to v7, fix import browser (Karma) issue Test Github actions checkout v2 Fix kzg error condition Client/Statemanager: new client cacheSize option (default: 2500000), adopted client tests, added state manager cache size/behavior note Fix bug in VM GeneralStateTestsRunner Run VM Blockchain and State tests without account cache Use reasonable cache sizes for VM Blockchain and State test runners Use reasonable cache sizes for VM Blockchain and State test runners (update) Introduce CacheType for StateManager with LRU and ORDERED_MAP options (default: ORDERED_MAP), use LRU for client, ORDERED_MAP for VM tests StateManager: remove BaseStateManager StateManager: internalize/remove _lookupStorageTrie() StateManager: remove del,put,get callback structure StateManager: move cache.ts to dedicated folder, rename to account.ts StateManager: move account cache module to dedicated folder, rename to AccountCache StateManager: move cache tests to dedicated folder, rename to account.spec.ts StateManager: extract generic cache functionality to superclass Cache StateManager: add storage cache class StateManager: integrate storage cache StateManager: rename checkpointing.spec.ts to checkpointing.account.spec.ts StateManager: streamlining account checkpointing tests StateManager: add checkpointing storage tests StateManager: rename stateManager.spec.ts to stateManager.account.spec.ts StateManager: extract storage and code tests to dedicated files, use storage cache on/off switch for storage tests Small fix Bug fixes More bug fixes Optimizations Client: integrate storage cache Various test fixes StateManager / VM: add DEBUG guards for StateManager cache StateManager: allow undefined for StateManager putAccount (interface change) Partial rework towards account -> key -> value double layer storage cache structure (abandoned for now) StateManager: Continuation with work towards account -> key -> value double layer storage cache structure StateManager: finished two layer storage cache structure, expanded storage checkpointing tests StateManager: expand ckeckpointing account tests Bug fixes StateManager: finalized clearContractStorage(), stricter account existance check StateManager: some storage cache clean-ups Doc improvements and bug fix EVM: fix for SELFDESTRUCT storage issue (blockchain test suicideThenCheckBalance failing) Client: rename cacheSize option to accountCache Client: add new option storageCache to set the storage cache size EVM: revert SELFDESTRUCT storage root fix StateManager: another SELFDESTRUCT storage cache fix attempt Continued fixes Fix StateManager copy() method Client: deactivate getStorageAt RPC method test, add TODO Clean-up * Move VM PR actions checkout version back to v3 * nits * Allow proofs of non-existence and fix `0x` return values * Remove unnecessary await * StateManager: more cache flush() await removals * VM: attempt to fix memory issue on test runners * VM: state test runner memory fix experiments (will clean this up later on) * VM GeneralStateTestsRunner memory allocation clean-ups * VM BlockchainTestRunner memory object de-allocation --------- Co-authored-by: acolytec3 <17355484+acolytec3@users.noreply.github.com> --- package-lock.json | 19 +- packages/client/bin/cli.ts | 12 + packages/client/lib/config.ts | 16 + packages/client/lib/execution/vmexecution.ts | 52 +- packages/client/lib/rpc/modules/eth.ts | 9 +- packages/client/lib/service/txpool.ts | 13 +- packages/client/lib/types.ts | 2 + packages/client/test/blockchain/chain.spec.ts | 2 +- packages/client/test/client.spec.ts | 8 +- packages/client/test/config.spec.ts | 4 +- .../client/test/execution/vmexecution.spec.ts | 4 +- .../client/test/integration/client.spec.ts | 10 +- .../integration/fullethereumservice.spec.ts | 2 +- .../client/test/integration/merge.spec.ts | 2 +- .../client/test/integration/miner.spec.ts | 2 +- .../client/test/integration/peerpool.spec.ts | 6 +- packages/client/test/integration/util.ts | 10 +- packages/client/test/miner/miner.spec.ts | 55 +- .../client/test/miner/pendingBlock.spec.ts | 8 +- packages/client/test/net/peer/peer.spec.ts | 2 +- .../client/test/net/peer/rlpxpeer.spec.ts | 10 +- packages/client/test/net/peerpool.spec.ts | 16 +- .../test/net/protocol/boundprotocol.spec.ts | 14 +- .../test/net/protocol/ethprotocol.spec.ts | 18 +- .../test/net/protocol/lesprotocol.spec.ts | 6 +- .../client/test/net/protocol/protocol.spec.ts | 6 +- .../test/net/protocol/snapprotocol.spec.ts | 28 +- .../test/net/server/libp2pserver.spec.ts | 13 +- .../client/test/net/server/rlpxserver.spec.ts | 30 +- .../test/rpc/engine/getBlobsBundleV1.spec.ts | 7 +- .../engine/getPayloadBodiesByHashV1.spec.ts | 18 +- .../engine/getPayloadBodiesByRangeV1.spec.ts | 12 +- .../client/test/rpc/eth/getStorageAt.spec.ts | 23 +- .../test/rpc/eth/sendRawTransaction.spec.ts | 16 +- packages/client/test/rpc/helpers.ts | 2 + .../test/service/fullethereumservice.spec.ts | 24 +- .../test/service/lightethereumservice.spec.ts | 8 +- packages/client/test/sim/4844.md | 9 +- packages/client/test/sim/snapsync.spec.ts | 2 + packages/client/test/sync/beaconsync.spec.ts | 16 +- .../test/sync/fetcher/accountfetcher.spec.ts | 10 +- .../test/sync/fetcher/blockfetcher.spec.ts | 10 +- .../client/test/sync/fetcher/fetcher.spec.ts | 12 +- .../test/sync/fetcher/headerfetcher.spec.ts | 8 +- .../sync/fetcher/reverseblockfetcher.spec.ts | 15 +- .../test/sync/fetcher/storagefetcher.spec.ts | 10 +- packages/client/test/sync/fullsync.spec.ts | 17 +- packages/client/test/sync/lightsync.spec.ts | 20 +- packages/client/test/sync/skeleton.spec.ts | 10 + packages/client/test/sync/snapsync.spec.ts | 6 +- packages/client/test/sync/sync.spec.ts | 2 +- packages/client/test/sync/txpool.spec.ts | 9 +- packages/client/test/util/rpc.spec.ts | 9 +- packages/evm/src/evm.ts | 51 +- packages/evm/src/interpreter.ts | 31 +- packages/evm/src/opcodes/functions.ts | 2 +- packages/evm/src/opcodes/gas.ts | 9 +- packages/evm/src/types.ts | 6 +- packages/evm/test/eips/eip-3860.spec.ts | 12 +- packages/evm/test/runCall.spec.ts | 19 +- packages/evm/test/runCode.spec.ts | 3 + packages/statemanager/package.json | 5 +- packages/statemanager/src/baseStateManager.ts | 142 ----- packages/statemanager/src/cache.ts | 192 ------- packages/statemanager/src/cache/account.ts | 276 ++++++++++ packages/statemanager/src/cache/cache.ts | 34 ++ packages/statemanager/src/cache/index.ts | 3 + packages/statemanager/src/cache/storage.ts | 374 +++++++++++++ packages/statemanager/src/cache/types.ts | 9 + .../statemanager/src/ethersStateManager.ts | 84 +-- packages/statemanager/src/index.ts | 8 +- packages/statemanager/src/interface.ts | 8 +- packages/statemanager/src/stateManager.ts | 487 ++++++++++++---- packages/statemanager/test/cache.spec.ts | 141 ----- .../statemanager/test/cache/account.spec.ts | 90 +++ .../statemanager/test/cache/storage.spec.ts | 87 +++ .../test/checkpointing.account.spec.ts | 310 +++++++++++ .../test/checkpointing.storage.spec.ts | 319 +++++++++++ .../test/ethersStateManager.spec.ts | 9 +- .../test/proofStateManager.spec.ts | 29 +- .../test/stateManager.account.spec.ts | 177 ++++++ .../test/stateManager.code.spec.ts | 157 ++++++ .../statemanager/test/stateManager.spec.ts | 520 ------------------ .../test/stateManager.storage.spec.ts | 158 ++++++ packages/vm/examples/helpers/account-utils.ts | 6 +- packages/vm/examples/run-solidity-contract.ts | 8 +- packages/vm/src/eei/eei.ts | 7 +- packages/vm/src/eei/vmState.ts | 17 +- packages/vm/src/runBlock.ts | 20 +- packages/vm/src/runTx.ts | 24 +- packages/vm/src/types.ts | 8 + packages/vm/src/vm.ts | 5 +- .../test/api/EIPs/eip-1559-FeeMarket.spec.ts | 19 +- .../test/api/EIPs/eip-3074-authcall.spec.ts | 45 +- packages/vm/test/api/EIPs/eip-3529.spec.ts | 4 +- .../EIPs/eip-3540-evm-object-format.spec.ts | 27 +- .../api/EIPs/eip-3651-warm-coinbase.spec.ts | 7 +- .../EIPs/eip-3670-eof-code-validation.spec.ts | 19 +- packages/vm/test/api/EIPs/eip-3860.spec.ts | 7 +- .../api/EIPs/eip-4895-withdrawals.spec.ts | 9 +- packages/vm/test/api/customChain.spec.ts | 2 +- packages/vm/test/api/eei.spec.ts | 18 +- packages/vm/test/api/runBlock.spec.ts | 16 +- packages/vm/test/api/runTx.spec.ts | 49 +- .../vm/test/api/state/accountExists.spec.ts | 13 +- .../tester/runners/BlockchainTestsRunner.ts | 19 +- .../tester/runners/GeneralStateTestsRunner.ts | 77 +-- packages/vm/test/util.ts | 3 +- 108 files changed, 3292 insertions(+), 1543 deletions(-) delete mode 100644 packages/statemanager/src/baseStateManager.ts delete mode 100644 packages/statemanager/src/cache.ts create mode 100644 packages/statemanager/src/cache/account.ts create mode 100644 packages/statemanager/src/cache/cache.ts create mode 100644 packages/statemanager/src/cache/index.ts create mode 100644 packages/statemanager/src/cache/storage.ts create mode 100644 packages/statemanager/src/cache/types.ts delete mode 100644 packages/statemanager/test/cache.spec.ts create mode 100644 packages/statemanager/test/cache/account.spec.ts create mode 100644 packages/statemanager/test/cache/storage.spec.ts create mode 100644 packages/statemanager/test/checkpointing.account.spec.ts create mode 100644 packages/statemanager/test/checkpointing.storage.spec.ts create mode 100644 packages/statemanager/test/stateManager.account.spec.ts create mode 100644 packages/statemanager/test/stateManager.code.spec.ts delete mode 100644 packages/statemanager/test/stateManager.spec.ts create mode 100644 packages/statemanager/test/stateManager.storage.spec.ts diff --git a/package-lock.json b/package-lock.json index e3d9ce83b7..659ee164f6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18160,7 +18160,8 @@ "debug": "^4.3.3", "ethereum-cryptography": "^1.1.2", "ethers": "^5.7.1", - "js-sdsl": "^4.1.4" + "js-sdsl": "^4.1.4", + "lru-cache": "^7.18.3" }, "devDependencies": { "@ethereumjs/block": "^4.2.1", @@ -18184,6 +18185,14 @@ "typescript": "^4.4.2" } }, + "packages/statemanager/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "engines": { + "node": ">=12" + } + }, "packages/trie": { "name": "@ethereumjs/trie", "version": "5.0.4", @@ -19805,11 +19814,19 @@ "karma-firefox-launcher": "^2.1.0", "karma-tap": "^4.2.0", "karma-typescript": "^5.5.3", + "lru-cache": "^7.18.3", "nyc": "^15.1.0", "standard": "^10.0.0", "tape": "^5.3.1", "ts-node": "^10.2.1", "typescript": "^4.4.2" + }, + "dependencies": { + "lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==" + } } }, "@ethereumjs/trie": { diff --git a/packages/client/bin/cli.ts b/packages/client/bin/cli.ts index cc079ae7d4..8aee7176fe 100755 --- a/packages/client/bin/cli.ts +++ b/packages/client/bin/cli.ts @@ -243,6 +243,16 @@ const args: ClientOpts = yargs(hideBin(process.argv)) 'Debug mode for reexecuting existing blocks (no services will be started), allowed input formats: 5,5-10', string: true, }) + .option('accountCache', { + describe: 'Size for the account cache (max number of accounts)', + number: true, + default: Config.ACCOUNT_CACHE, + }) + .option('storageCache', { + describe: 'Size for the storage cache (max number of contracts)', + number: true, + default: Config.STORAGE_CACHE, + }) .option('debugCode', { describe: 'Generate code for local debugging (internal usage mostly)', boolean: true, @@ -721,6 +731,8 @@ async function run() { discV4: args.discV4, dnsAddr: args.dnsAddr, numBlocksPerIteration: args.numBlocksPerIteration, + accountCache: args.accountCache, + storageCache: args.storageCache, dnsNetworks: args.dnsNetworks, extIP: args.extIP, key, diff --git a/packages/client/lib/config.ts b/packages/client/lib/config.ts index 13b2c0e582..47378c5e24 100644 --- a/packages/client/lib/config.ts +++ b/packages/client/lib/config.ts @@ -193,6 +193,16 @@ export interface ConfigOptions { */ numBlocksPerIteration?: number + /** + * Size for the account cache (max number of accounts) + */ + accountCache?: number + + /** + * Size for the storage cache (max number of contracts) + */ + storageCache?: number + /** * Generate code for local debugging, currently providing a * code snippet which can be used to run blocks on the @@ -295,6 +305,8 @@ export class Config { public static readonly MAXPEERS_DEFAULT = 25 public static readonly DNSADDR_DEFAULT = '8.8.8.8' public static readonly NUM_BLOCKS_PER_ITERATION = 50 + public static readonly ACCOUNT_CACHE = 1000000 + public static readonly STORAGE_CACHE = 200000 public static readonly DEBUGCODE_DEFAULT = false public static readonly SAFE_REORG_DISTANCE = 100 public static readonly SKELETON_FILL_CANONICAL_BACKSTEP = 100 @@ -327,6 +339,8 @@ export class Config { public readonly maxPeers: number public readonly dnsAddr: string public readonly numBlocksPerIteration: number + public readonly accountCache: number + public readonly storageCache: number public readonly debugCode: boolean public readonly discDns: boolean public readonly discV4: boolean @@ -381,6 +395,8 @@ export class Config { this.maxPeers = options.maxPeers ?? Config.MAXPEERS_DEFAULT this.dnsAddr = options.dnsAddr ?? Config.DNSADDR_DEFAULT this.numBlocksPerIteration = options.numBlocksPerIteration ?? Config.NUM_BLOCKS_PER_ITERATION + this.accountCache = options.accountCache ?? Config.ACCOUNT_CACHE + this.storageCache = options.storageCache ?? Config.STORAGE_CACHE this.debugCode = options.debugCode ?? Config.DEBUGCODE_DEFAULT this.mine = options.mine ?? false this.isSingleNode = options.isSingleNode ?? false diff --git a/packages/client/lib/execution/vmexecution.ts b/packages/client/lib/execution/vmexecution.ts index 45114c38f0..813109c9a9 100644 --- a/packages/client/lib/execution/vmexecution.ts +++ b/packages/client/lib/execution/vmexecution.ts @@ -6,6 +6,7 @@ import { } from '@ethereumjs/blockchain/dist/db/helpers' import { ConsensusType, Hardfork } from '@ethereumjs/common' import { DefaultStateManager } from '@ethereumjs/statemanager' +import { CacheType } from '@ethereumjs/statemanager/dist/cache' import { Trie } from '@ethereumjs/trie' import { Lock, bytesToHex, bytesToPrefixedHexString, equalsBytes } from '@ethereumjs/util' import { VM } from '@ethereumjs/vm' @@ -34,6 +35,12 @@ export class VMExecution extends Execution { /** Maximally tolerated block time before giving a warning on console */ private MAX_TOLERATED_BLOCK_TIME = 12 + /** + * Display state cache stats every num blocks + */ + private CACHE_STATS_NUM_BLOCKS = 500 + private cacheStatsCount = 0 + /** * Create new VM execution module */ @@ -46,8 +53,20 @@ export class VMExecution extends Execution { useKeyHashing: true, }) + this.config.logger.info(`Initializing account cache size=${this.config.accountCache}`) + this.config.logger.info(`Initializing storage cache size=${this.config.storageCache}`) const stateManager = new DefaultStateManager({ trie, + accountCacheOpts: { + deactivate: false, + type: CacheType.LRU, + size: this.config.accountCache, + }, + storageCacheOpts: { + deactivate: false, + type: CacheType.LRU, + size: this.config.storageCache, + }, }) this.vm = new (VM as any)({ @@ -280,6 +299,12 @@ export class VMExecution extends Execution { if (headBlock === undefined || reorg) { const headBlock = await blockchain.getBlock(block.header.parentHash) parentState = headBlock.header.stateRoot + + if (reorg) { + this.config.logger.info( + `Chain reorg happened, set new head to block number=${headBlock.header.number}, clearing state cache for VM execution.` + ) + } } // run block, update head if valid try { @@ -314,9 +339,11 @@ export class VMExecution extends Execution { throw Error('Execution stopped') } const beforeTS = Date.now() + this.cacheStats(this.vm) const result = await this.vm.runBlock({ block, root: parentState, + clearCache: reorg ? true : false, skipBlockValidation, skipHeaderValidation: true, }) @@ -482,7 +509,7 @@ export class VMExecution extends Execution { const block = await vm.blockchain.getBlock(blockNumber) const parentBlock = await vm.blockchain.getBlock(block.header.parentHash) // Set the correct state root - await vm.stateManager.setStateRoot(parentBlock.header.stateRoot) + const root = parentBlock.header.stateRoot if (typeof vm.blockchain.getTotalDifficulty !== 'function') { throw new Error('cannot get iterator head: blockchain has no getTotalDifficulty function') } @@ -493,7 +520,13 @@ export class VMExecution extends Execution { // we are skipping header validation because the block has been picked from the // blockchain and header should have already been validated while putBlock const beforeTS = Date.now() - const res = await vm.runBlock({ block, skipHeaderValidation: true }) + this.cacheStats(vm) + const res = await vm.runBlock({ + block, + root, + clearCache: false, + skipHeaderValidation: true, + }) const afterTS = Date.now() const diffSec = Math.round((afterTS - beforeTS) / 1000) const msg = `Executed block num=${blockNumber} hash=${bytesToPrefixedHexString( @@ -529,4 +562,19 @@ export class VMExecution extends Execution { } } } + + cacheStats(vm: VM) { + this.cacheStatsCount += 1 + if (this.cacheStatsCount === this.CACHE_STATS_NUM_BLOCKS) { + let stats = (vm.stateManager as any)._accountCache.stats() + this.config.logger.info( + `Account cache stats size=${stats.size} reads=${stats.reads} hits=${stats.hits} writes=${stats.writes}` + ) + stats = (vm.stateManager as any)._storageCache.stats() + this.config.logger.info( + `Storage cache stats size=${stats.size} reads=${stats.reads} hits=${stats.hits} writes=${stats.writes}` + ) + this.cacheStatsCount = 0 + } + } } diff --git a/packages/client/lib/rpc/modules/eth.ts b/packages/client/lib/rpc/modules/eth.ts index a8b16d7cde..91060ffa60 100644 --- a/packages/client/lib/rpc/modules/eth.ts +++ b/packages/client/lib/rpc/modules/eth.ts @@ -26,7 +26,6 @@ import type { Block, JsonRpcBlock } from '@ethereumjs/block' import type { Log } from '@ethereumjs/evm' import type { Proof } from '@ethereumjs/statemanager' import type { FeeMarketEIP1559Transaction, Transaction, TypedTransaction } from '@ethereumjs/tx' -import type { Account } from '@ethereumjs/util' import type { PostByzantiumTxReceipt, PreByzantiumTxReceipt, TxReceipt, VM } from '@ethereumjs/vm' type GetLogsParams = { @@ -517,6 +516,9 @@ export class Eth { const vm = await this._vm.copy() await vm.stateManager.setStateRoot(block.header.stateRoot) const account = await vm.stateManager.getAccount(address) + if (account === undefined) { + throw new Error(`could not read account`) + } return bigIntToHex(account.balance) } @@ -687,7 +689,10 @@ export class Eth { await vm.stateManager.setStateRoot(block.header.stateRoot) const address = Address.fromString(addressHex) - const account: Account = await vm.stateManager.getAccount(address) + const account = await vm.stateManager.getAccount(address) + if (account === undefined) { + throw new Error(`could not read account`) + } return bigIntToHex(account.nonce) } diff --git a/packages/client/lib/service/txpool.ts b/packages/client/lib/service/txpool.ts index 475f779efb..930965a643 100644 --- a/packages/client/lib/service/txpool.ts +++ b/packages/client/lib/service/txpool.ts @@ -1,5 +1,5 @@ import { BlobEIP4844Transaction, Capability } from '@ethereumjs/tx' -import { Address, bytesToHex, equalsBytes, hexStringToBytes } from '@ethereumjs/util' +import { Account, Address, bytesToHex, equalsBytes, hexStringToBytes } from '@ethereumjs/util' import Heap = require('qheap') import type { Config } from '../config' @@ -303,7 +303,10 @@ export class TxPool { const vmCopy = await this.vm.copy() // Set state root to latest block so that account balance is correct when doing balance check await vmCopy.stateManager.setStateRoot(block.stateRoot) - const account = await vmCopy.stateManager.getAccount(senderAddress) + let account = await vmCopy.stateManager.getAccount(senderAddress) + if (account === undefined) { + account = new Account() + } if (account.nonce > tx.nonce) { throw new Error( `0x${sender} tries to send a tx with nonce ${tx.nonce}, but account has nonce ${account.nonce} (tx nonce too low)` @@ -694,7 +697,11 @@ export class TxPool { .map((obj) => obj.tx) .sort((a, b) => Number(a.nonce - b.nonce)) // Check if the account nonce matches the lowest known tx nonce - const { nonce } = await vm.eei.getAccount(new Address(hexStringToBytes(address))) + let account = await vm.eei.getAccount(new Address(hexStringToBytes(address))) + if (account === undefined) { + account = new Account() + } + const { nonce } = account if (txsSortedByNonce[0].nonce !== nonce) { // Account nonce does not match the lowest known tx nonce, // therefore no txs from this address are currently executable diff --git a/packages/client/lib/types.ts b/packages/client/lib/types.ts index 051d16b7d8..db85ebc942 100644 --- a/packages/client/lib/types.ts +++ b/packages/client/lib/types.ts @@ -144,6 +144,8 @@ export interface ClientOpts { maxPeers?: number dnsAddr?: string numBlocksPerIteration?: number + accountCache?: number + storageCache?: number dnsNetworks?: string[] executeBlocks?: string debugCode?: boolean diff --git a/packages/client/test/blockchain/chain.spec.ts b/packages/client/test/blockchain/chain.spec.ts index e5a388f9db..287c20b5c7 100644 --- a/packages/client/test/blockchain/chain.spec.ts +++ b/packages/client/test/blockchain/chain.spec.ts @@ -11,7 +11,7 @@ import { Config } from '../../lib/config' import type { BlockData, HeaderData } from '@ethereumjs/block' -const config = new Config() +const config = new Config({ accountCache: 10000, storageCache: 1000 }) tape('[Chain]', (t) => { t.test('should test blockchain DB is initialized', async (t) => { diff --git a/packages/client/test/client.spec.ts b/packages/client/test/client.spec.ts index 99a7007d00..94b6d9b68f 100644 --- a/packages/client/test/client.spec.ts +++ b/packages/client/test/client.spec.ts @@ -5,7 +5,7 @@ import { Config } from '../lib/config' import { PeerPool } from '../lib/net/peerpool' tape('[EthereumClient]', async (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) class FullEthereumService { open() {} start() {} @@ -39,7 +39,7 @@ tape('[EthereumClient]', async (t) => { const { EthereumClient } = await import('../lib/client') t.test('should initialize correctly', async (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const client = await EthereumClient.create({ config }) t.ok(client.services[0] instanceof FullEthereumService, 'added service') t.end() @@ -48,7 +48,7 @@ tape('[EthereumClient]', async (t) => { t.test('should open', async (t) => { t.plan(2) const servers = [new Server()] as any - const config = new Config({ servers }) + const config = new Config({ servers, accountCache: 10000, storageCache: 1000 }) const client = await EthereumClient.create({ config }) await client.open() @@ -58,7 +58,7 @@ tape('[EthereumClient]', async (t) => { t.test('should start/stop', async (t) => { const servers = [new Server()] as any - const config = new Config({ servers }) + const config = new Config({ servers, accountCache: 10000, storageCache: 1000 }) const client = await EthereumClient.create({ config }) await client.start() t.ok(client.started, 'started') diff --git a/packages/client/test/config.spec.ts b/packages/client/test/config.spec.ts index af7dcb2ba7..92fa3a4237 100644 --- a/packages/client/test/config.spec.ts +++ b/packages/client/test/config.spec.ts @@ -11,7 +11,7 @@ tape('[Config]', (t) => { }) t.test('Initialization with parameters passed', (t) => { - const config = new Config({ maxPeers: 10 }) + const config = new Config({ maxPeers: 10, accountCache: 10000, storageCache: 1000 }) t.equal(config.maxPeers, 10) t.end() }) @@ -36,7 +36,7 @@ tape('[Config]', (t) => { t.test('peer discovery default mainnet setting', (t) => { const common = new Common({ chain: Chain.Mainnet }) - const config = new Config({ common }) + const config = new Config({ common, accountCache: 10000, storageCache: 1000 }) t.equal(config.discDns, false, 'disables DNS peer discovery for mainnet') t.equal(config.discV4, true, 'enables DNS peer discovery for mainnet') t.end() diff --git a/packages/client/test/execution/vmexecution.spec.ts b/packages/client/test/execution/vmexecution.spec.ts index d26929a0a0..02a66d3e6b 100644 --- a/packages/client/test/execution/vmexecution.spec.ts +++ b/packages/client/test/execution/vmexecution.spec.ts @@ -13,7 +13,7 @@ import testnet = require('../testdata/common/testnet.json') tape('[VMExecution]', async (t) => { t.test('Initialization', async (t) => { const vm = await VM.create() - const config = new Config({ vm, transports: [] }) + const config = new Config({ vm, transports: [], accountCache: 10000, storageCache: 1000 }) const chain = await Chain.create({ config }) const exec = new VMExecution({ config, chain }) t.equals(exec.vm, vm, 'should use vm provided') @@ -21,7 +21,7 @@ tape('[VMExecution]', async (t) => { }) async function testSetup(blockchain: Blockchain, common?: Common) { - const config = new Config({ common, transports: [] }) + const config = new Config({ common, transports: [], accountCache: 10000, storageCache: 1000 }) const chain = await Chain.create({ config, blockchain }) const exec = new VMExecution({ config, chain }) await chain.open() diff --git a/packages/client/test/integration/client.spec.ts b/packages/client/test/integration/client.spec.ts index cf91f0229b..53886f4129 100644 --- a/packages/client/test/integration/client.spec.ts +++ b/packages/client/test/integration/client.spec.ts @@ -7,9 +7,15 @@ import { Event } from '../../lib/types' import { MockServer } from './mocks/mockserver' tape('[Integration:EthereumClient]', async (t) => { - const serverConfig = new Config() + const serverConfig = new Config({ accountCache: 10000, storageCache: 1000 }) const servers = [new MockServer({ config: serverConfig }) as any] - const config = new Config({ servers, syncmode: SyncMode.Full, lightserv: false }) + const config = new Config({ + servers, + syncmode: SyncMode.Full, + lightserv: false, + accountCache: 10000, + storageCache: 1000, + }) // attach server to centralized event bus ;(config.servers[0].config as any).events = config.events diff --git a/packages/client/test/integration/fullethereumservice.spec.ts b/packages/client/test/integration/fullethereumservice.spec.ts index 3f2996085a..85e8f1d973 100644 --- a/packages/client/test/integration/fullethereumservice.spec.ts +++ b/packages/client/test/integration/fullethereumservice.spec.ts @@ -15,7 +15,7 @@ import { MockChain } from './mocks/mockchain' import { MockServer } from './mocks/mockserver' import { destroy } from './util' -const config = new Config() +const config = new Config({ accountCache: 10000, storageCache: 1000 }) tape('[Integration:FullEthereumService]', async (t) => { // Stub out setStateRoot since correct state root doesn't exist in mock state. diff --git a/packages/client/test/integration/merge.spec.ts b/packages/client/test/integration/merge.spec.ts index 68722a4dee..3ef75a7991 100644 --- a/packages/client/test/integration/merge.spec.ts +++ b/packages/client/test/integration/merge.spec.ts @@ -72,7 +72,7 @@ tape('[Integration:Merge]', async (t) => { ], ] async function minerSetup(common: Common): Promise<[MockServer, FullEthereumService]> { - const config = new Config({ common }) + const config = new Config({ common, accountCache: 10000, storageCache: 1000 }) const server = new MockServer({ config }) const blockchain = await Blockchain.create({ common, diff --git a/packages/client/test/integration/miner.spec.ts b/packages/client/test/integration/miner.spec.ts index 7bd5f11896..dc6776e975 100644 --- a/packages/client/test/integration/miner.spec.ts +++ b/packages/client/test/integration/miner.spec.ts @@ -49,7 +49,7 @@ tape('[Integration:Miner]', async (t) => { ], ] async function minerSetup(): Promise<[MockServer, FullEthereumService]> { - const config = new Config({ common }) + const config = new Config({ common, accountCache: 10000, storageCache: 1000 }) const server = new MockServer({ config }) const blockchain = await Blockchain.create({ diff --git a/packages/client/test/integration/peerpool.spec.ts b/packages/client/test/integration/peerpool.spec.ts index a8cb483a74..011403481c 100644 --- a/packages/client/test/integration/peerpool.spec.ts +++ b/packages/client/test/integration/peerpool.spec.ts @@ -12,10 +12,10 @@ import { wait } from './util' tape('[Integration:PeerPool]', async (t) => { async function setup(protocols: EthProtocol[] = []): Promise<[MockServer, PeerPool]> { - const serverConfig = new Config() + const serverConfig = new Config({ accountCache: 10000, storageCache: 1000 }) const server = new MockServer({ config: serverConfig }) as any server.addProtocols(protocols) - const config = new Config({ servers: [server] }) + const config = new Config({ servers: [server], accountCache: 10000, storageCache: 1000 }) await server.start() const pool = new PeerPool({ config }) await pool.open() @@ -64,7 +64,7 @@ tape('[Integration:PeerPool]', async (t) => { }) t.test('should handle peer messages', async (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const blockchain = await Blockchain.create({ validateBlocks: false, validateConsensus: false, diff --git a/packages/client/test/integration/util.ts b/packages/client/test/integration/util.ts index e91e92705e..e548440a88 100644 --- a/packages/client/test/integration/util.ts +++ b/packages/client/test/integration/util.ts @@ -28,7 +28,15 @@ export async function setup( const lightserv = syncmode === 'full' const common = options.common?.copy() - const config = new Config({ syncmode, lightserv, minPeers, common, safeReorgDistance: 0 }) + const config = new Config({ + syncmode, + lightserv, + minPeers, + common, + safeReorgDistance: 0, + accountCache: 10000, + storageCache: 1000, + }) const server = new MockServer({ config, location }) const blockchain = await Blockchain.create({ diff --git a/packages/client/test/miner/miner.spec.ts b/packages/client/test/miner/miner.spec.ts index 1c24e89bfe..80a313b4b9 100644 --- a/packages/client/test/miner/miner.spec.ts +++ b/packages/client/test/miner/miner.spec.ts @@ -90,7 +90,14 @@ tape('[Miner]', async (t) => { const common = new Common({ chain: CommonChain.Rinkeby, hardfork: Hardfork.Berlin }) common.setMaxListeners(50) const accounts: [Address, Uint8Array][] = [[A.address, A.privateKey]] - const config = new Config({ transports: [], accounts, mine: true, common }) + const config = new Config({ + transports: [], + accountCache: 10000, + storageCache: 1000, + accounts, + mine: true, + common, + }) config.events.setMaxListeners(50) const createTx = ( @@ -270,7 +277,15 @@ tape('[Miner]', async (t) => { t.test('assembleBlocks() -> with saveReceipts', async (t) => { t.plan(9) const chain = new FakeChain() as any - const config = new Config({ transports: [], accounts, mine: true, common, saveReceipts: true }) + const config = new Config({ + transports: [], + accountCache: 10000, + storageCache: 1000, + accounts, + mine: true, + common, + saveReceipts: true, + }) const service = new FullEthereumService({ config, chain, @@ -327,7 +342,14 @@ tape('[Miner]', async (t) => { baseChain: CommonChain.Rinkeby, hardfork: Hardfork.London, }) - const config = new Config({ transports: [], accounts, mine: true, common }) + const config = new Config({ + transports: [], + accountCache: 10000, + storageCache: 1000, + accounts, + mine: true, + common, + }) const chain = new FakeChain() as any const block = Block.fromBlockData({}, { common }) Object.defineProperty(chain, 'headers', { @@ -429,7 +451,14 @@ tape('[Miner]', async (t) => { t.test('assembleBlocks() -> should stop assembling when a new block is received', async (t) => { t.plan(2) const chain = new FakeChain() as any - const config = new Config({ transports: [], accounts, mine: true, common }) + const config = new Config({ + transports: [], + accountCache: 10000, + storageCache: 1000, + accounts, + mine: true, + common, + }) const service = new FullEthereumService({ config, chain, @@ -482,7 +511,14 @@ tape('[Miner]', async (t) => { } const common = Common.custom(customChainParams, { baseChain: CommonChain.Rinkeby }) common.setHardforkByBlockNumber(0) - const config = new Config({ transports: [], accounts, mine: true, common }) + const config = new Config({ + transports: [], + accountCache: 10000, + storageCache: 1000, + accounts, + mine: true, + common, + }) const chain = await Chain.create({ config }) await chain.open() const service = new FullEthereumService({ @@ -549,7 +585,14 @@ tape('[Miner]', async (t) => { t.test('should handle mining ethash PoW', async (t) => { const common = new Common({ chain: CommonChain.Ropsten, hardfork: Hardfork.Istanbul }) ;(common as any)._chainParams['genesis'].difficulty = 1 - const config = new Config({ transports: [], accounts, mine: true, common }) + const config = new Config({ + transports: [], + accountCache: 10000, + storageCache: 1000, + accounts, + mine: true, + common, + }) const chain = await Chain.create({ config }) await chain.open() const service = new FullEthereumService({ diff --git a/packages/client/test/miner/pendingBlock.spec.ts b/packages/client/test/miner/pendingBlock.spec.ts index a6cc28c83d..f86390efc3 100644 --- a/packages/client/test/miner/pendingBlock.spec.ts +++ b/packages/client/test/miner/pendingBlock.spec.ts @@ -45,7 +45,13 @@ const setBalance = async (vm: VM, address: Address, balance: bigint) => { } const common = new Common({ chain: CommonChain.Rinkeby, hardfork: Hardfork.Berlin }) -const config = new Config({ transports: [], common, logger: getLogger({ loglevel: 'debug' }) }) +const config = new Config({ + transports: [], + common, + accountCache: 10000, + storageCache: 1000, + logger: getLogger({ loglevel: 'debug' }), +}) const setup = () => { const stateManager = { diff --git a/packages/client/test/net/peer/peer.spec.ts b/packages/client/test/net/peer/peer.spec.ts index ef4dcf164e..81c532e517 100644 --- a/packages/client/test/net/peer/peer.spec.ts +++ b/packages/client/test/net/peer/peer.spec.ts @@ -7,7 +7,7 @@ import { Peer } from '../../../lib/net/peer' import { Event } from '../../../lib/types' tape('[Peer]', (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const peer = new Peer({ config, id: '0123456789abcdef', diff --git a/packages/client/test/net/peer/rlpxpeer.spec.ts b/packages/client/test/net/peer/rlpxpeer.spec.ts index 8b7fbab794..f2ea71f7a5 100644 --- a/packages/client/test/net/peer/rlpxpeer.spec.ts +++ b/packages/client/test/net/peer/rlpxpeer.spec.ts @@ -16,7 +16,7 @@ tape('[RlpxPeer]', async (t) => { const { RlpxPeer } = await import('../../../lib/net/peer/rlpxpeer') t.test('should initialize correctly', async (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const peer = new RlpxPeer({ config, id: 'abcdef0123', @@ -52,7 +52,7 @@ tape('[RlpxPeer]', async (t) => { }) t.test('should connect to peer', async (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const proto0 = { name: 'les', versions: [4] } as any const peer = new RlpxPeer({ config, @@ -71,7 +71,7 @@ tape('[RlpxPeer]', async (t) => { t.test('should handle peer events', async (t) => { t.plan(5) - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const peer = new RlpxPeer({ config, id: 'abcdef0123', host: '10.0.0.1', port: 1234 }) const rlpxPeer = { id: 'zyx321', getDisconnectPrefix: td.func() } as any ;(peer as any).bindProtocols = td.func() @@ -106,7 +106,7 @@ tape('[RlpxPeer]', async (t) => { }) t.test('should accept peer connection', async (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const peer: any = new RlpxPeer({ config, id: 'abcdef0123', host: '10.0.0.1', port: 1234 }) peer.bindProtocols = td.func() td.when(peer.bindProtocols('rlpxpeer' as any)).thenResolve(null) @@ -116,7 +116,7 @@ tape('[RlpxPeer]', async (t) => { }) t.test('should bind protocols', async (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const protocols = [{ name: 'proto0' }] as any const peer = new RlpxPeer({ config, id: 'abcdef0123', protocols, host: '10.0.0.1', port: 1234 }) const proto0 = new (class Proto0 extends EventEmitter {})() diff --git a/packages/client/test/net/peerpool.spec.ts b/packages/client/test/net/peerpool.spec.ts index 0e01ec1922..233986ab26 100644 --- a/packages/client/test/net/peerpool.spec.ts +++ b/packages/client/test/net/peerpool.spec.ts @@ -15,7 +15,7 @@ tape('[PeerPool]', async (t) => { const { PeerPool } = await import('../../lib/net/peerpool') t.test('should initialize', (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const pool = new PeerPool({ config }) t.notOk((pool as any).pool.size, 'empty pool') t.notOk((pool as any).opened, 'not open') @@ -25,7 +25,11 @@ tape('[PeerPool]', async (t) => { t.test('should open/close', async (t) => { t.plan(3) const server = {} - const config = new Config({ servers: [server as RlpxServer] }) + const config = new Config({ + servers: [server as RlpxServer], + accountCache: 10000, + storageCache: 1000, + }) const pool = new PeerPool({ config }) const peer = new MockPeer({ id: 'peer', @@ -52,7 +56,7 @@ tape('[PeerPool]', async (t) => { t.test('should connect/disconnect peer', (t) => { t.plan(2) const peer = new EventEmitter() as any - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const pool = new PeerPool({ config }) ;(peer as any).id = 'abc' ;(peer as any).handleMessageQueue = td.func() @@ -68,7 +72,7 @@ tape('[PeerPool]', async (t) => { t.test('should check contains', (t) => { const peer = new Peer('abc') - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const pool = new PeerPool({ config }) pool.add(peer) t.ok(pool.contains(peer.id), 'found peer') @@ -77,7 +81,7 @@ tape('[PeerPool]', async (t) => { t.test('should get idle peers', (t) => { const peers = [new Peer(1), new Peer(2), new Peer(3)] - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const pool = new PeerPool({ config }) peers[1].idle = true for (const p of peers) { @@ -94,7 +98,7 @@ tape('[PeerPool]', async (t) => { t.test('should ban peer', (t) => { const peers = [{ id: 1 }, { id: 2, server: { ban: td.func() } }] - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const pool = new PeerPool({ config }) for (const p of peers as any) { pool.add(p) diff --git a/packages/client/test/net/protocol/boundprotocol.spec.ts b/packages/client/test/net/protocol/boundprotocol.spec.ts index d6ddb7019e..051b74d476 100644 --- a/packages/client/test/net/protocol/boundprotocol.spec.ts +++ b/packages/client/test/net/protocol/boundprotocol.spec.ts @@ -29,7 +29,7 @@ tape('[BoundProtocol]', (t) => { t.test('should add methods for messages with a response', (t) => { const sender = new Sender() - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const bound = new BoundProtocol({ config, protocol, @@ -42,7 +42,7 @@ tape('[BoundProtocol]', (t) => { t.test('should get/set status', (t) => { const sender = new Sender() - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const bound = new BoundProtocol({ config, protocol, @@ -56,7 +56,7 @@ tape('[BoundProtocol]', (t) => { }) t.test('should do handshake', async (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const sender = new EventEmitter() as Sender const bound = new BoundProtocol({ config, @@ -71,7 +71,7 @@ tape('[BoundProtocol]', (t) => { }) t.test('should handle incoming without resolver', async (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const sender = new Sender() const bound = new BoundProtocol({ config, @@ -93,7 +93,7 @@ tape('[BoundProtocol]', (t) => { }) t.test('should perform send', (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const sender = new Sender() sender.sendMessage = td.func() const bound = new BoundProtocol({ @@ -110,7 +110,7 @@ tape('[BoundProtocol]', (t) => { }) t.test('should perform request', async (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const sender = new Sender() const bound = new BoundProtocol({ config, @@ -138,7 +138,7 @@ tape('[BoundProtocol]', (t) => { }) t.test('should timeout request', async (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const sender = td.object('Sender') const bound = new BoundProtocol({ config, diff --git a/packages/client/test/net/protocol/ethprotocol.spec.ts b/packages/client/test/net/protocol/ethprotocol.spec.ts index c66d7fe09f..d2801c14f0 100644 --- a/packages/client/test/net/protocol/ethprotocol.spec.ts +++ b/packages/client/test/net/protocol/ethprotocol.spec.ts @@ -10,7 +10,7 @@ import { EthProtocol } from '../../../lib/net/protocol' tape('[EthProtocol]', (t) => { t.test('should get properties', async (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const chain = await Chain.create({ config }) const p = new EthProtocol({ config, chain }) t.ok(typeof p.name === 'string', 'get name') @@ -20,7 +20,7 @@ tape('[EthProtocol]', (t) => { }) t.test('should open correctly', async (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const chain = await Chain.create({ config }) const p = new EthProtocol({ config, chain }) await p.open() @@ -30,7 +30,7 @@ tape('[EthProtocol]', (t) => { }) t.test('should encode/decode status', async (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const chain = await Chain.create({ config }) const p = new EthProtocol({ config, chain }) Object.defineProperty(chain, 'networkId', { @@ -79,7 +79,7 @@ tape('[EthProtocol]', (t) => { }) t.test('verify that NewBlock handler encodes/decodes correctly', async (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const chain = await Chain.create({ config }) const p = new EthProtocol({ config, chain }) const td = BigInt(100) @@ -98,7 +98,7 @@ tape('[EthProtocol]', (t) => { }) t.test('verify that GetReceipts handler encodes/decodes correctly', async (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const chain = await Chain.create({ config }) const p = new EthProtocol({ config, chain }) const block = Block.fromBlockData({}) @@ -121,6 +121,8 @@ tape('[EthProtocol]', (t) => { const config = new Config({ transports: [], common: new Common({ chain: Config.CHAIN_DEFAULT, hardfork: Hardfork.London }), + accountCache: 10000, + storageCache: 1000, }) const chain = await Chain.create({ config }) const p = new EthProtocol({ config, chain }) @@ -146,6 +148,8 @@ tape('[EthProtocol]', (t) => { const config = new Config({ transports: [], common: new Common({ chain: Config.CHAIN_DEFAULT, hardfork: Hardfork.London }), + accountCache: 10000, + storageCache: 1000, }) const chain = await Chain.create({ config }) const p = new EthProtocol({ config, chain }) @@ -213,6 +217,8 @@ tape('[EthProtocol]', (t) => { hardfork: Hardfork.Merge, eips: [4895, 4844], }), + accountCache: 10000, + storageCache: 1000, }) config.synchronized = true const chain = await Chain.create({ config }) @@ -247,6 +253,8 @@ tape('[EthProtocol]', (t) => { const config = new Config({ transports: [], common: new Common({ chain: Config.CHAIN_DEFAULT, hardfork: Hardfork.London }), + accountCache: 10000, + storageCache: 1000, }) const chain = await Chain.create({ config }) const p = new EthProtocol({ config, chain }) diff --git a/packages/client/test/net/protocol/lesprotocol.spec.ts b/packages/client/test/net/protocol/lesprotocol.spec.ts index c3e195395c..cc336e63fe 100644 --- a/packages/client/test/net/protocol/lesprotocol.spec.ts +++ b/packages/client/test/net/protocol/lesprotocol.spec.ts @@ -7,7 +7,7 @@ import { FlowControl, LesProtocol } from '../../../lib/net/protocol' tape('[LesProtocol]', (t) => { t.test('should get properties', async (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const chain = await Chain.create({ config }) const p = new LesProtocol({ config, chain }) t.ok(typeof p.name === 'string', 'get name') @@ -17,7 +17,7 @@ tape('[LesProtocol]', (t) => { }) t.test('should open correctly', async (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const chain = await Chain.create({ config }) const p = new LesProtocol({ config, chain }) await p.open() @@ -27,7 +27,7 @@ tape('[LesProtocol]', (t) => { }) t.test('should encode/decode status', async (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const chain = await Chain.create({ config }) const flow = new FlowControl({ bl: 1000, diff --git a/packages/client/test/net/protocol/protocol.spec.ts b/packages/client/test/net/protocol/protocol.spec.ts index 0ed217a6ef..0960b3166f 100644 --- a/packages/client/test/net/protocol/protocol.spec.ts +++ b/packages/client/test/net/protocol/protocol.spec.ts @@ -13,7 +13,7 @@ tape('[Protocol]', (t) => { } class TestProtocol extends Protocol { constructor() { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) super({ config }) } @@ -35,7 +35,7 @@ tape('[Protocol]', (t) => { } t.test('should throw if missing abstract methods', (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const p = new Protocol({ config }) t.throws(() => p.versions, /Unimplemented/) t.throws(() => p.messages, /Unimplemented/) @@ -45,7 +45,7 @@ tape('[Protocol]', (t) => { }) t.test('should handle open', async (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const p = new Protocol({ config }) await p.open() t.ok(p.opened, 'is open') diff --git a/packages/client/test/net/protocol/snapprotocol.spec.ts b/packages/client/test/net/protocol/snapprotocol.spec.ts index a614a7fb6d..9dca7985b0 100644 --- a/packages/client/test/net/protocol/snapprotocol.spec.ts +++ b/packages/client/test/net/protocol/snapprotocol.spec.ts @@ -24,7 +24,7 @@ import { SnapProtocol } from '../../../lib/net/protocol' tape('[SnapProtocol]', (t) => { t.test('should get properties', async (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const chain = await Chain.create({ config }) const p = new SnapProtocol({ config, chain }) t.ok(typeof p.name === 'string', 'get name') @@ -34,7 +34,7 @@ tape('[SnapProtocol]', (t) => { }) t.test('should open correctly', async (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const chain = await Chain.create({ config }) const p = new SnapProtocol({ config, chain }) await p.open() @@ -44,7 +44,7 @@ tape('[SnapProtocol]', (t) => { }) t.test('GetAccountRange should encode/decode correctly', async (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const chain = await Chain.create({ config }) const p = new SnapProtocol({ config, chain }) const root = new Uint8Array(0) @@ -102,7 +102,7 @@ tape('[SnapProtocol]', (t) => { }) t.test('AccountRange should encode/decode correctly', async (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const chain = await Chain.create({ config }) const p = new SnapProtocol({ config, chain }) /* eslint-disable @typescript-eslint/no-use-before-define */ @@ -145,7 +145,7 @@ tape('[SnapProtocol]', (t) => { }) t.test('AccountRange encode/decode should handle account slim body correctly', async (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const chain = await Chain.create({ config }) const pSlim = new SnapProtocol({ config, chain }) const pFull = new SnapProtocol({ config, chain, convertSlimBody: true }) @@ -183,7 +183,7 @@ tape('[SnapProtocol]', (t) => { }) t.test('AccountRange should verify a real sample', async (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const chain = await Chain.create({ config }) const p = new SnapProtocol({ config, chain }) @@ -223,7 +223,7 @@ tape('[SnapProtocol]', (t) => { }) t.test('GetStorageRanges should encode/decode correctly', async (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const chain = await Chain.create({ config }) const p = new SnapProtocol({ config, chain }) const root = new Uint8Array(0) @@ -287,7 +287,7 @@ tape('[SnapProtocol]', (t) => { }) t.test('StorageRanges should encode/decode correctly', async (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const chain = await Chain.create({ config }) const p = new SnapProtocol({ config, chain }) @@ -318,7 +318,7 @@ tape('[SnapProtocol]', (t) => { }) t.test('StorageRanges should verify a real sample', async (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const chain = await Chain.create({ config }) const p = new SnapProtocol({ config, chain }) @@ -363,7 +363,7 @@ tape('[SnapProtocol]', (t) => { }) t.test('GetByteCodes should encode/decode correctly', async (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const chain = await Chain.create({ config }) const p = new SnapProtocol({ config, chain }) const reqId = BigInt(1) @@ -403,7 +403,7 @@ tape('[SnapProtocol]', (t) => { }) t.test('ByteCodes should encode/decode correctly', async (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const chain = await Chain.create({ config }) const p = new SnapProtocol({ config, chain }) @@ -427,7 +427,7 @@ tape('[SnapProtocol]', (t) => { }) t.test('ByteCodes should verify a real sample', async (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const chain = await Chain.create({ config }) const p = new SnapProtocol({ config, chain }) @@ -449,7 +449,7 @@ tape('[SnapProtocol]', (t) => { }) t.test('GetTrieNodes should encode/decode correctly', async (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const chain = await Chain.create({ config }) const p = new SnapProtocol({ config, chain }) @@ -491,7 +491,7 @@ tape('[SnapProtocol]', (t) => { }) t.test('TrieNodes should encode/decode correctly with real sample', async (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const chain = await Chain.create({ config }) const p = new SnapProtocol({ config, chain }) diff --git a/packages/client/test/net/server/libp2pserver.spec.ts b/packages/client/test/net/server/libp2pserver.spec.ts index ea5c249c43..14660f4210 100644 --- a/packages/client/test/net/server/libp2pserver.spec.ts +++ b/packages/client/test/net/server/libp2pserver.spec.ts @@ -42,7 +42,7 @@ tape('[Libp2pServer]', async (t) => { const { Libp2pServer } = await import('../../../lib/net/server/libp2pserver') t.test('should initialize correctly', async (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const multiaddrs = [ multiaddr('/ip4/192.0.2.1/tcp/12345'), multiaddr('/ip4/192.0.2.1/tcp/23456'), @@ -70,7 +70,7 @@ tape('[Libp2pServer]', async (t) => { }) t.test('should get peer info', async (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const server = new Libp2pServer({ config }) const connection = td.object() connection.remotePeer = 'id0' @@ -79,7 +79,7 @@ tape('[Libp2pServer]', async (t) => { }) t.test('should create peer', async (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const multiaddrs = [multiaddr('/ip4/6.6.6.6')] const server = new Libp2pServer({ config, multiaddrs }) const peerId = { @@ -95,7 +95,12 @@ tape('[Libp2pServer]', async (t) => { t.test('should start/stop server and test banning', async (t) => { t.plan(12) - const config = new Config({ transports: [], logger: getLogger({ loglevel: 'off' }) }) + const config = new Config({ + transports: [], + logger: getLogger({ loglevel: 'off' }), + accountCache: 10000, + storageCache: 1000, + }) const multiaddrs = [multiaddr('/ip4/6.6.6.6')] const server = new Libp2pServer({ config, multiaddrs, key: utf8ToBytes('4') }) const protos: any = [ diff --git a/packages/client/test/net/server/rlpxserver.spec.ts b/packages/client/test/net/server/rlpxserver.spec.ts index f34ef52380..9f346ac631 100644 --- a/packages/client/test/net/server/rlpxserver.spec.ts +++ b/packages/client/test/net/server/rlpxserver.spec.ts @@ -45,7 +45,7 @@ tape('[RlpxServer]', async (t) => { ).thenResolve() t.test('should initialize correctly', async (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const server = new RlpxServer({ config, bootnodes: '10.0.0.1:1234,enode://abcd@10.0.0.2:1234', @@ -62,7 +62,7 @@ tape('[RlpxServer]', async (t) => { }) t.test('should start/stop server', async (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const server = new RlpxServer({ config, bootnodes: '10.0.0.1:1234,10.0.0.2:1234', @@ -93,7 +93,12 @@ tape('[RlpxServer]', async (t) => { t.test('should bootstrap with dns acquired peers', async (t) => { const dnsPeerInfo = { address: '10.0.0.5', udpPort: 1234, tcpPort: 1234 } - const config = new Config({ transports: [], discDns: true }) + const config = new Config({ + transports: [], + accountCache: 10000, + storageCache: 1000, + discDns: true, + }) const server = new RlpxServer({ config, dnsNetworks: ['enrtree:A'], @@ -111,7 +116,7 @@ tape('[RlpxServer]', async (t) => { }) t.test('should return rlpx server info with ip4 as default', async (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const mockId = '0123' const server = new RlpxServer({ config, @@ -150,7 +155,12 @@ tape('[RlpxServer]', async (t) => { }) t.test('should return rlpx server info with ip6', async (t) => { - const config = new Config({ transports: [], extIP: '::' }) + const config = new Config({ + transports: [], + accountCache: 10000, + storageCache: 1000, + extIP: '::', + }) const mockId = '0123' const server = new RlpxServer({ config, @@ -190,7 +200,7 @@ tape('[RlpxServer]', async (t) => { t.test('should handle errors', (t) => { t.plan(3) let count = 0 - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const server = new RlpxServer({ config }) server.config.events.on(Event.SERVER_ERROR, (err) => { count = count + 1 @@ -206,7 +216,7 @@ tape('[RlpxServer]', async (t) => { }) t.test('should ban peer', (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const server = new RlpxServer({ config }) t.notOk(server.ban('123'), 'not started') server.started = true @@ -218,7 +228,7 @@ tape('[RlpxServer]', async (t) => { t.test('should init dpt', (t) => { t.plan(1) - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const server = new RlpxServer({ config }) ;(server as any).initDpt().catch((error: Error) => { throw error @@ -230,7 +240,7 @@ tape('[RlpxServer]', async (t) => { t.test('should init rlpx', async (t) => { t.plan(4) - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const server = new RlpxServer({ config }) const rlpxPeer = new RlpxPeer() td.when(rlpxPeer.getId()).thenReturn(new Uint8Array([1])) @@ -256,7 +266,7 @@ tape('[RlpxServer]', async (t) => { t.test('should handles errors from id-less peers', async (t) => { t.plan(1) - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const server = new RlpxServer({ config }) const rlpxPeer = new RlpxPeer() td.when(rlpxPeer.getId()).thenReturn(utf8ToBytes('test')) diff --git a/packages/client/test/rpc/engine/getBlobsBundleV1.spec.ts b/packages/client/test/rpc/engine/getBlobsBundleV1.spec.ts index 0b976a8580..f6a25ec396 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 } from '@ethereumjs/tx' -import { Address, hexStringToBytes, initKZG } from '@ethereumjs/util' +import { Account, Address, hexStringToBytes, initKZG } from '@ethereumjs/util' import * as kzg from 'c-kzg' import * as tape from 'tape' @@ -63,10 +63,11 @@ tape(`${method}: call with known payload`, async (t) => { common.setHardfork(Hardfork.ShardingForkDev) const pkey = hexStringToBytes('9c9996335451aab4fc4eac58e31a8c300e095cdbcee532d53d09280e83360355') const address = Address.fromPrivateKey(pkey) + await service.execution.vm.stateManager.putAccount(address, new Account()) const account = await service.execution.vm.stateManager.getAccount(address) - account.balance = 0xfffffffffffffffn - await service.execution.vm.stateManager.putAccount(address, account) + account!.balance = 0xfffffffffffffffn + await service.execution.vm.stateManager.putAccount(address, account!) let req = params('engine_forkchoiceUpdatedV2', validPayload) let payloadId let expectRes = (res: any) => { diff --git a/packages/client/test/rpc/engine/getPayloadBodiesByHashV1.spec.ts b/packages/client/test/rpc/engine/getPayloadBodiesByHashV1.spec.ts index 32fb207324..a268128599 100644 --- a/packages/client/test/rpc/engine/getPayloadBodiesByHashV1.spec.ts +++ b/packages/client/test/rpc/engine/getPayloadBodiesByHashV1.spec.ts @@ -2,7 +2,13 @@ import { Block, BlockHeader } from '@ethereumjs/block' import { Hardfork } from '@ethereumjs/common' import { DefaultStateManager } from '@ethereumjs/statemanager' import { TransactionFactory } from '@ethereumjs/tx' -import { Address, bytesToPrefixedHexString, hexStringToBytes, randomBytes } from '@ethereumjs/util' +import { + Account, + Address, + bytesToPrefixedHexString, + hexStringToBytes, + randomBytes, +} from '@ethereumjs/util' import * as tape from 'tape' import { TOO_LARGE_REQUEST } from '../../../lib/rpc/error-code' @@ -43,10 +49,11 @@ tape(`${method}: call with valid parameters`, async (t) => { common.setHardfork(Hardfork.ShardingForkDev) const pkey = hexStringToBytes('9c9996335451aab4fc4eac58e31a8c300e095cdbcee532d53d09280e83360355') const address = Address.fromPrivateKey(pkey) + await service.execution.vm.stateManager.putAccount(address, new Account()) const account = await service.execution.vm.stateManager.getAccount(address) - account.balance = 0xfffffffffffffffn - await service.execution.vm.stateManager.putAccount(address, account) + account!.balance = 0xfffffffffffffffn + await service.execution.vm.stateManager.putAccount(address, account!) const tx = TransactionFactory.fromTxData( { type: 0x01, @@ -132,10 +139,11 @@ tape(`${method}: call with valid parameters on pre-Shanghai block`, async (t) => common.setHardfork(Hardfork.London) const pkey = hexStringToBytes('9c9996335451aab4fc4eac58e31a8c300e095cdbcee532d53d09280e83360355') const address = Address.fromPrivateKey(pkey) + await service.execution.vm.stateManager.putAccount(address, new Account()) const account = await service.execution.vm.stateManager.getAccount(address) - account.balance = 0xfffffffffffffffn - await service.execution.vm.stateManager.putAccount(address, account) + account!.balance = 0xfffffffffffffffn + await service.execution.vm.stateManager.putAccount(address, account!) const tx = TransactionFactory.fromTxData( { type: 0x01, diff --git a/packages/client/test/rpc/engine/getPayloadBodiesByRangeV1.spec.ts b/packages/client/test/rpc/engine/getPayloadBodiesByRangeV1.spec.ts index e83ba7d41e..650e43bde8 100644 --- a/packages/client/test/rpc/engine/getPayloadBodiesByRangeV1.spec.ts +++ b/packages/client/test/rpc/engine/getPayloadBodiesByRangeV1.spec.ts @@ -2,7 +2,7 @@ import { Block, BlockHeader } from '@ethereumjs/block' import { Hardfork } from '@ethereumjs/common' import { DefaultStateManager } from '@ethereumjs/statemanager' import { TransactionFactory } from '@ethereumjs/tx' -import { Address, bytesToPrefixedHexString, hexStringToBytes } from '@ethereumjs/util' +import { Account, Address, bytesToPrefixedHexString, hexStringToBytes } from '@ethereumjs/util' import * as tape from 'tape' import { INVALID_PARAMS, TOO_LARGE_REQUEST } from '../../../lib/rpc/error-code' @@ -52,10 +52,11 @@ tape(`${method}: call with valid parameters`, async (t) => { common.setHardfork(Hardfork.ShardingForkDev) const pkey = hexStringToBytes('9c9996335451aab4fc4eac58e31a8c300e095cdbcee532d53d09280e83360355') const address = Address.fromPrivateKey(pkey) + await service.execution.vm.stateManager.putAccount(address, new Account()) const account = await service.execution.vm.stateManager.getAccount(address) - account.balance = 0xfffffffffffffffn - await service.execution.vm.stateManager.putAccount(address, account) + account!.balance = 0xfffffffffffffffn + await service.execution.vm.stateManager.putAccount(address, account!) const tx = TransactionFactory.fromTxData( { type: 0x01, @@ -144,10 +145,11 @@ tape(`${method}: call with valid parameters on pre-Shanghai hardfork`, async (t) common.setHardfork(Hardfork.London) const pkey = hexStringToBytes('9c9996335451aab4fc4eac58e31a8c300e095cdbcee532d53d09280e83360355') const address = Address.fromPrivateKey(pkey) + await service.execution.vm.stateManager.putAccount(address, new Account()) const account = await service.execution.vm.stateManager.getAccount(address) - account.balance = 0xfffffffffffffffn - await service.execution.vm.stateManager.putAccount(address, account) + account!.balance = 0xfffffffffffffffn + await service.execution.vm.stateManager.putAccount(address, account!) const tx = TransactionFactory.fromTxData( { type: 0x01, diff --git a/packages/client/test/rpc/eth/getStorageAt.spec.ts b/packages/client/test/rpc/eth/getStorageAt.spec.ts index a4374714f5..9d46ca8f37 100644 --- a/packages/client/test/rpc/eth/getStorageAt.spec.ts +++ b/packages/client/test/rpc/eth/getStorageAt.spec.ts @@ -2,8 +2,8 @@ import { Block } from '@ethereumjs/block' import { Blockchain } from '@ethereumjs/blockchain' import { Chain, Common, Hardfork } from '@ethereumjs/common' import { Transaction } from '@ethereumjs/tx' -import { Address, bigIntToHex, bytesToPrefixedHexString, hexStringToBytes } from '@ethereumjs/util' -import { keccak256 } from 'ethereum-cryptography/keccak' +import { Account, Address, bigIntToHex } from '@ethereumjs/util' +//import { keccak256 } from 'ethereum-cryptography/keccak' import * as tape from 'tape' import { INVALID_PARAMS } from '../../../lib/rpc/error-code' @@ -28,6 +28,10 @@ tape(`${method}: call with valid arguments`, async (t) => { const server = startRPC(manager.getMethods()) const { execution } = client.services.find((s) => s.name === 'eth') as FullEthereumService + await execution.vm.stateManager.putAccount( + Address.fromString('0x9288f8f702cbfb8cc5890819c1c1e2746e684d07'), + new Account() + ) t.notEqual(execution, undefined, 'should have valid execution') const { vm } = execution @@ -109,8 +113,11 @@ tape(`${method}: call with valid arguments`, async (t) => { await vm.runBlock({ block: block2, generate: true, skipBlockValidation: true }) await vm.blockchain.putBlock(ranBlock2!) + // TODO: fix tests + // (deactivated along https://github.com/ethereumjs/ethereumjs-monorepo/pull/2618, + // storage cache work, 2023-04-07) // verify storage of pos0 is accurate - let req = params(method, [createdAddress!.toString(), '0x0', 'latest']) + /*let req = params(method, [createdAddress!.toString(), '0x0', 'latest']) let expectRes = (res: any) => { const msg = 'should return the correct storage value (pos0)' t.equal( @@ -119,11 +126,11 @@ tape(`${method}: call with valid arguments`, async (t) => { msg ) } - await baseRequest(t, server, req, 200, expectRes, false) + await baseRequest(t, server, req, 200, expectRes, false)*/ // verify storage of pos1 is accurate // pos1["0xccfd725760a68823ff1e062f4cc97e1360e8d997"] - const key = keccak256( + /**const key = keccak256( hexStringToBytes( '000000000000000000000000ccfd725760a68823ff1e062f4cc97e1360e8d997' + '0000000000000000000000000000000000000000000000000000000000000001' @@ -138,10 +145,10 @@ tape(`${method}: call with valid arguments`, async (t) => { msg ) } - await baseRequest(t, server, req, 200, expectRes, false) + await baseRequest(t, server, req, 200, expectRes, false)*/ // call with unsupported block argument - req = params(method, [createdAddress!.toString(), '0x0', 'pending']) - expectRes = checkError(t, INVALID_PARAMS, '"pending" is not yet supported') + const req = params(method, [createdAddress!.toString(), '0x0', 'pending']) + const expectRes = checkError(t, INVALID_PARAMS, '"pending" is not yet supported') await baseRequest(t, server, req, 200, expectRes) }) diff --git a/packages/client/test/rpc/eth/sendRawTransaction.spec.ts b/packages/client/test/rpc/eth/sendRawTransaction.spec.ts index 7ed196b5f1..c6b7863dd3 100644 --- a/packages/client/test/rpc/eth/sendRawTransaction.spec.ts +++ b/packages/client/test/rpc/eth/sendRawTransaction.spec.ts @@ -3,6 +3,7 @@ import { Chain, Common, Hardfork } from '@ethereumjs/common' import { DefaultStateManager } from '@ethereumjs/statemanager' import { BlobEIP4844Transaction, FeeMarketEIP1559Transaction, Transaction } from '@ethereumjs/tx' import { + Account, blobsToCommitments, bytesToPrefixedHexString, commitmentsToVersionedHashes, @@ -47,9 +48,10 @@ tape(`${method}: call with valid arguments`, async (t) => { const address = transaction.getSenderAddress() const vm = (client.services.find((s) => s.name === 'eth') as FullEthereumService).execution.vm + await vm.stateManager.putAccount(address, new Account()) const account = await vm.stateManager.getAccount(address) - account.balance = BigInt('40100000') - await vm.stateManager.putAccount(address, account) + account!.balance = BigInt('40100000') + await vm.stateManager.putAccount(address, account!) const req = params(method, [txData]) const expectRes = (res: any) => { @@ -191,9 +193,10 @@ tape(`${method}: call with no peers`, async (t) => { const address = transaction.getSenderAddress() const vm = (client.services.find((s) => s.name === 'eth') as FullEthereumService).execution.vm + await vm.stateManager.putAccount(address, new Account()) const account = await vm.stateManager.getAccount(address) - account.balance = BigInt('40100000') - await vm.stateManager.putAccount(address, account) + account!.balance = BigInt('40100000') + await vm.stateManager.putAccount(address, account!) const req = params(method, [txData]) @@ -267,9 +270,10 @@ tape('blob EIP 4844 transaction', async (t) => { { common } ).sign(pk) const vm = (client.services.find((s) => s.name === 'eth') as FullEthereumService).execution.vm + await vm.stateManager.putAccount(tx.getSenderAddress(), new Account()) const account = await vm.stateManager.getAccount(tx.getSenderAddress()) - account.balance = BigInt(0xfffffffffffff) - await vm.stateManager.putAccount(tx.getSenderAddress(), account) + account!.balance = BigInt(0xfffffffffffff) + await vm.stateManager.putAccount(tx.getSenderAddress(), account!) const req = params(method, [bytesToPrefixedHexString(tx.serializeNetworkWrapper())]) const req2 = params(method, [bytesToPrefixedHexString(replacementTx.serializeNetworkWrapper())]) diff --git a/packages/client/test/rpc/helpers.ts b/packages/client/test/rpc/helpers.ts index 53325fac28..75428d6d17 100644 --- a/packages/client/test/rpc/helpers.ts +++ b/packages/client/test/rpc/helpers.ts @@ -74,6 +74,8 @@ export function createClient(clientOpts: Partial = {}) { common, saveReceipts: clientOpts.enableMetaDB, txLookupLimit: clientOpts.txLookupLimit, + accountCache: 10000, + storageCache: 1000, }) const blockchain = clientOpts.blockchain ?? mockBlockchain() diff --git a/packages/client/test/service/fullethereumservice.spec.ts b/packages/client/test/service/fullethereumservice.spec.ts index 0bbe155f7a..4d6cd20bc1 100644 --- a/packages/client/test/service/fullethereumservice.spec.ts +++ b/packages/client/test/service/fullethereumservice.spec.ts @@ -66,7 +66,7 @@ tape('[FullEthereumService]', async (t) => { const { FullEthereumService } = await import('../../lib/service/fullethereumservice') t.test('should initialize correctly', async (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const chain = await Chain.create({ config }) const service = new FullEthereumService({ config, chain }) t.ok(service.synchronizer instanceof FullSynchronizer, 'full mode') @@ -75,7 +75,7 @@ tape('[FullEthereumService]', async (t) => { }) t.test('should get protocols', async (t) => { - let config = new Config({ transports: [] }) + let config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const chain = await Chain.create({ config }) let service = new FullEthereumService({ config, chain }) t.ok(service.protocols.filter((p) => p instanceof EthProtocol).length > 0, 'full protocol') @@ -96,7 +96,7 @@ tape('[FullEthereumService]', async (t) => { t.test('should open', async (t) => { t.plan(3) const server = td.object() as any - const config = new Config({ servers: [server] }) + const config = new Config({ servers: [server], accountCache: 10000, storageCache: 1000 }) const chain = await Chain.create({ config }) const service = new FullEthereumService({ config, chain }) await service.open() @@ -117,7 +117,7 @@ tape('[FullEthereumService]', async (t) => { t.test('should start/stop', async (t) => { const server = td.object() as any - const config = new Config({ servers: [server] }) + const config = new Config({ servers: [server], accountCache: 10000, storageCache: 1000 }) const chain = await Chain.create({ config }) const service = new FullEthereumService({ config, chain }) @@ -131,7 +131,7 @@ tape('[FullEthereumService]', async (t) => { }) t.test('should correctly handle GetBlockHeaders', async (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const chain = await Chain.create({ config }) chain.getHeaders = () => [{ number: 1n }] as any const service = new FullEthereumService({ config, chain }) @@ -181,7 +181,7 @@ tape('[FullEthereumService]', async (t) => { t.test( 'should call handleNewBlock on NewBlock and handleNewBlockHashes on NewBlockHashes', async (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const chain = await Chain.create({ config }) const service = new FullEthereumService({ config, chain }) await service.handle({ name: 'NewBlock', data: [{}, BigInt(1)] }, 'eth', undefined as any) @@ -210,7 +210,7 @@ tape('[FullEthereumService]', async (t) => { t.test('should ban peer for sending NewBlock/NewBlockHashes after merge', async (t) => { t.plan(2) const common = new Common({ chain: 'mainnet', hardfork: Hardfork.Merge }) - const config = new Config({ common, transports: [] }) + const config = new Config({ common, transports: [], accountCache: 10000, storageCache: 1000 }) const chain = await Chain.create({ config }) const service = new FullEthereumService({ config, chain }) service.pool.ban = () => { @@ -222,7 +222,7 @@ tape('[FullEthereumService]', async (t) => { }) t.test('should send Receipts on GetReceipts', async (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const chain = await Chain.create({ config }) const service = new FullEthereumService({ config, chain }) service.execution = { @@ -267,7 +267,7 @@ tape('[FullEthereumService]', async (t) => { }) t.test('should handle Transactions', async (st) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const chain = await Chain.create({ config }) const service = new FullEthereumService({ config, chain }) service.txPool.handleAnnouncedTxs = async (msg, _peer, _pool) => { @@ -290,7 +290,7 @@ tape('[FullEthereumService]', async (t) => { }) t.test('should handle NewPooledTransactionHashes', async (st) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const chain = await Chain.create({ config }) const service = new FullEthereumService({ config, chain }) service.txPool.handleAnnouncedTxHashes = async (msg, _peer, _pool) => { @@ -309,7 +309,7 @@ tape('[FullEthereumService]', async (t) => { }) t.test('should handle GetPooledTransactions', async (st) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const chain = await Chain.create({ config }) const service = new FullEthereumService({ config, chain }) ;(service.txPool as any).validate = () => {} @@ -334,7 +334,7 @@ tape('[FullEthereumService]', async (t) => { t.test('should start on beacon sync when past merge', async (t) => { const common = Common.fromGethGenesis(genesisJSON, { chain: 'post-merge' }) common.setHardforkByBlockNumber(BigInt(0), BigInt(0)) - const config = new Config({ transports: [], common }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000, common }) const chain = await Chain.create({ config }) let service = new FullEthereumService({ config, chain }) t.ok(service.beaconSync, 'beacon sync should be available') diff --git a/packages/client/test/service/lightethereumservice.spec.ts b/packages/client/test/service/lightethereumservice.spec.ts index c82df629ad..9b7d62d567 100644 --- a/packages/client/test/service/lightethereumservice.spec.ts +++ b/packages/client/test/service/lightethereumservice.spec.ts @@ -33,7 +33,7 @@ tape('[LightEthereumService]', async (t) => { const { LightEthereumService } = await import('../../lib/service/lightethereumservice') t.test('should initialize correctly', async (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const chain = await Chain.create({ config }) const service = new LightEthereumService({ config, chain }) t.ok(service.synchronizer instanceof LightSynchronizer, 'light sync') @@ -42,7 +42,7 @@ tape('[LightEthereumService]', async (t) => { }) t.test('should get protocols', async (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const chain = await Chain.create({ config }) const service = new LightEthereumService({ config, chain }) t.ok(service.protocols[0] instanceof LesProtocol, 'light protocols') @@ -52,7 +52,7 @@ tape('[LightEthereumService]', async (t) => { t.test('should open', async (t) => { t.plan(3) const server = td.object() as any - const config = new Config({ servers: [server] }) + const config = new Config({ servers: [server], accountCache: 10000, storageCache: 1000 }) const chain = await Chain.create({ config }) const service = new LightEthereumService({ config, chain }) await service.open() @@ -73,7 +73,7 @@ tape('[LightEthereumService]', async (t) => { t.test('should start/stop', async (t) => { const server = td.object() as any - const config = new Config({ servers: [server] }) + const config = new Config({ servers: [server], accountCache: 10000, storageCache: 1000 }) const chain = await Chain.create({ config }) const service = new LightEthereumService({ config, chain }) await service.start() diff --git a/packages/client/test/sim/4844.md b/packages/client/test/sim/4844.md index dd004b69be..4b23249ac6 100644 --- a/packages/client/test/sim/4844.md +++ b/packages/client/test/sim/4844.md @@ -19,21 +19,16 @@ OR, you can use the `txGenerator.ts` script as follows: 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 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` - +`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 - -`WITH_PEER=syncpeer LODE_IMAGE=g11tech/lodestar:decoupled DATADIR=path/to/your/data/directory 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/snapsync.spec.ts b/packages/client/test/sim/snapsync.spec.ts index aa6f8f6278..5be6083f8e 100644 --- a/packages/client/test/sim/snapsync.spec.ts +++ b/packages/client/test/sim/snapsync.spec.ts @@ -174,6 +174,8 @@ async function createSnapClient(common: any, customGenesisState: any, bootnodes: bootnodes, multiaddrs: [], logger, + accountCache: 10000, + storageCache: 1000, discDns: false, discV4: false, port: 30304, diff --git a/packages/client/test/sync/beaconsync.spec.ts b/packages/client/test/sync/beaconsync.spec.ts index c9be394c3f..fd7fd9f550 100644 --- a/packages/client/test/sync/beaconsync.spec.ts +++ b/packages/client/test/sync/beaconsync.spec.ts @@ -42,7 +42,7 @@ tape('[BeaconSynchronizer]', async (t) => { const { BeaconSynchronizer } = await import('../../lib/sync/beaconsync') t.test('should initialize correctly', async (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const pool = new PeerPool() as any const chain = await Chain.create({ config }) const skeleton = new Skeleton({ chain, config, metaDB: new MemoryLevel() }) @@ -52,7 +52,7 @@ tape('[BeaconSynchronizer]', async (t) => { }) t.test('should open', async (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const pool = new PeerPool() as any const chain = await Chain.create({ config }) const skeleton = new Skeleton({ chain, config, metaDB: new MemoryLevel() }) @@ -67,7 +67,7 @@ tape('[BeaconSynchronizer]', async (t) => { }) t.test('should get height', async (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const pool = new PeerPool() as any const chain = await Chain.create({ config }) const skeleton = new Skeleton({ chain, config, metaDB: new MemoryLevel() }) @@ -83,7 +83,7 @@ tape('[BeaconSynchronizer]', async (t) => { }) t.test('should find best', async (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const pool = new PeerPool() as any const chain = await Chain.create({ config }) const skeleton = new Skeleton({ chain, config, metaDB: new MemoryLevel() }) @@ -115,6 +115,8 @@ tape('[BeaconSynchronizer]', async (t) => { transports: [], safeReorgDistance: 0, skeletonSubchainMergeMinimum: 0, + accountCache: 10000, + storageCache: 1000, }) const pool = new PeerPool() as any const chain = await Chain.create({ config }) @@ -166,6 +168,8 @@ tape('[BeaconSynchronizer]', async (t) => { transports: [], safeReorgDistance: 0, skeletonSubchainMergeMinimum: 1000, + accountCache: 10000, + storageCache: 1000, }) const pool = new PeerPool() as any const chain = await Chain.create({ config }) @@ -195,7 +199,7 @@ tape('[BeaconSynchronizer]', async (t) => { }) t.test('should extend and set with a valid head', async (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const pool = new PeerPool() as any const chain = await Chain.create({ config }) const skeleton = new Skeleton({ chain, config, metaDB: new MemoryLevel() }) @@ -224,7 +228,7 @@ tape('[BeaconSynchronizer]', async (t) => { }) t.test('syncWithPeer should return early if skeleton is already linked', async (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const pool = new PeerPool() as any const chain = await Chain.create({ config }) const skeleton = new Skeleton({ chain, config, metaDB: new MemoryLevel() }) diff --git a/packages/client/test/sync/fetcher/accountfetcher.spec.ts b/packages/client/test/sync/fetcher/accountfetcher.spec.ts index 719b41c560..b731cde810 100644 --- a/packages/client/test/sync/fetcher/accountfetcher.spec.ts +++ b/packages/client/test/sync/fetcher/accountfetcher.spec.ts @@ -47,7 +47,7 @@ tape('[AccountFetcher]', async (t) => { }) t.test('should process', (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const pool = new PeerPool() as any const fetcher = new AccountFetcher({ config, @@ -83,7 +83,7 @@ tape('[AccountFetcher]', async (t) => { }) t.test('should adopt correctly', (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const pool = new PeerPool() as any const fetcher = new AccountFetcher({ config, @@ -126,7 +126,7 @@ tape('[AccountFetcher]', async (t) => { }) t.test('should request correctly', async (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const pool = new PeerPool() as any const fetcher = new AccountFetcher({ config, @@ -168,7 +168,7 @@ tape('[AccountFetcher]', async (t) => { }) t.test('should verify proof correctly', async (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const chain = await Chain.create({ config }) const p = new SnapProtocol({ config, chain }) const pool = new PeerPool() as any @@ -247,7 +247,7 @@ tape('[AccountFetcher]', async (t) => { }) t.test('should find a fetchable peer', async (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const pool = new PeerPool() as any const fetcher = new AccountFetcher({ config, diff --git a/packages/client/test/sync/fetcher/blockfetcher.spec.ts b/packages/client/test/sync/fetcher/blockfetcher.spec.ts index a846a8c9f0..7e644a3c6f 100644 --- a/packages/client/test/sync/fetcher/blockfetcher.spec.ts +++ b/packages/client/test/sync/fetcher/blockfetcher.spec.ts @@ -94,7 +94,7 @@ tape('[BlockFetcher]', async (t) => { }) t.test('should process', async (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const pool = new PeerPool() as any const chain = await Chain.create({ config }) const fetcher = new BlockFetcher({ @@ -111,7 +111,7 @@ tape('[BlockFetcher]', async (t) => { }) t.test('should adopt correctly', async (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const pool = new PeerPool() as any const chain = await Chain.create({ config }) const fetcher = new BlockFetcher({ @@ -139,7 +139,7 @@ tape('[BlockFetcher]', async (t) => { }) t.test('should find a fetchable peer', async (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const pool = new PeerPool() as any const chain = await Chain.create({ config }) const fetcher = new BlockFetcher({ @@ -155,7 +155,7 @@ tape('[BlockFetcher]', async (t) => { }) t.test('should request correctly', async (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const pool = new PeerPool() as any const chain = await Chain.create({ config }) const fetcher = new BlockFetcher({ @@ -186,7 +186,7 @@ tape('[BlockFetcher]', async (t) => { }) t.test('should parse bodies correctly', async (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) config.chainCommon.getHardforkByBlockNumber = td.func() td.when( diff --git a/packages/client/test/sync/fetcher/fetcher.spec.ts b/packages/client/test/sync/fetcher/fetcher.spec.ts index b58983cd5e..67b39806b3 100644 --- a/packages/client/test/sync/fetcher/fetcher.spec.ts +++ b/packages/client/test/sync/fetcher/fetcher.spec.ts @@ -27,7 +27,7 @@ class FetcherTest extends Fetcher { tape('[Fetcher]', (t) => { t.test('should handle bad result', (t) => { t.plan(2) - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const fetcher = new FetcherTest({ config, pool: td.object() }) const job: any = { peer: {}, state: 'active' } ;(fetcher as any).running = true @@ -41,7 +41,7 @@ tape('[Fetcher]', (t) => { t.test('should handle failure', (t) => { t.plan(2) - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const fetcher = new FetcherTest({ config, pool: td.object() }) const job = { peer: {}, state: 'active' } ;(fetcher as any).running = true @@ -53,7 +53,7 @@ tape('[Fetcher]', (t) => { t.test('should handle expiration', (t) => { t.plan(2) - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const fetcher = new FetcherTest({ config, pool: td.object(), @@ -81,7 +81,7 @@ tape('[Fetcher]', (t) => { t.test('should handle queue management', (t) => { t.plan(3) - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const fetcher = new FetcherTest({ config, pool: td.object(), @@ -109,7 +109,7 @@ tape('[Fetcher]', (t) => { t.test('should re-enqueue on a non-fatal error', (t) => { t.plan(1) - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const fetcher = new FetcherTest({ config, pool: td.object(), timeout: 5000 }) const task = { first: BigInt(50), count: 10 } const job: any = { peer: {}, task, state: 'active', index: 0 } @@ -141,7 +141,7 @@ tape('[Fetcher]', (t) => { }) t.test('should handle fatal errors correctly', (st) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const fetcher = new FetcherTest({ config, pool: td.object(), timeout: 5000 }) const task = { first: BigInt(50), count: 10 } const job: any = { peer: {}, task, state: 'active', index: 0 } diff --git a/packages/client/test/sync/fetcher/headerfetcher.spec.ts b/packages/client/test/sync/fetcher/headerfetcher.spec.ts index 3828c91265..3b84f04568 100644 --- a/packages/client/test/sync/fetcher/headerfetcher.spec.ts +++ b/packages/client/test/sync/fetcher/headerfetcher.spec.ts @@ -17,7 +17,7 @@ tape('[HeaderFetcher]', async (t) => { const { HeaderFetcher } = await import('../../../lib/sync/fetcher/headerfetcher') t.test('should process', (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const pool = new PeerPool() const flow = td.object() const fetcher = new HeaderFetcher({ config, pool, flow }) @@ -35,7 +35,7 @@ tape('[HeaderFetcher]', async (t) => { }) t.test('should adopt correctly', (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const pool = new PeerPool() as any const flow = td.object() const fetcher = new HeaderFetcher({ @@ -62,7 +62,7 @@ tape('[HeaderFetcher]', async (t) => { }) t.test('should find a fetchable peer', async (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const pool = new PeerPool() const fetcher = new HeaderFetcher({ config, pool }) td.when((fetcher as any).pool.idle(td.matchers.anything())).thenReturn('peer0') @@ -71,7 +71,7 @@ tape('[HeaderFetcher]', async (t) => { }) t.test('should request correctly', async (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const pool = new PeerPool() as any const flow = td.object() const fetcher = new HeaderFetcher({ diff --git a/packages/client/test/sync/fetcher/reverseblockfetcher.spec.ts b/packages/client/test/sync/fetcher/reverseblockfetcher.spec.ts index 9311f07544..a33bbf24b0 100644 --- a/packages/client/test/sync/fetcher/reverseblockfetcher.spec.ts +++ b/packages/client/test/sync/fetcher/reverseblockfetcher.spec.ts @@ -76,7 +76,7 @@ tape('[ReverseBlockFetcher]', async (t) => { }) t.test('should process', async (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const pool = new PeerPool() as any const chain = await Chain.create({ config }) const skeleton = new Skeleton({ chain, config, metaDB: new MemoryLevel() }) @@ -95,7 +95,7 @@ tape('[ReverseBlockFetcher]', async (t) => { }) t.test('should adopt correctly', async (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const pool = new PeerPool() as any const chain = await Chain.create({ config }) const skeleton = new Skeleton({ chain, config, metaDB: new MemoryLevel() }) @@ -125,7 +125,7 @@ tape('[ReverseBlockFetcher]', async (t) => { }) t.test('should find a fetchable peer', async (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const pool = new PeerPool() as any const chain = await Chain.create({ config }) const skeleton = new Skeleton({ chain, config, metaDB: new MemoryLevel() }) @@ -143,7 +143,7 @@ tape('[ReverseBlockFetcher]', async (t) => { }) t.test('should request correctly', async (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const pool = new PeerPool() as any const chain = await Chain.create({ config }) const skeleton = new Skeleton({ chain, config, metaDB: new MemoryLevel() }) @@ -222,7 +222,12 @@ tape('[ReverseBlockFetcher]', async (t) => { t.test('should restart the fetcher when subchains are merged', async (st) => { td.reset() - const config = new Config({ transports: [], skeletonSubchainMergeMinimum: 0 }) + const config = new Config({ + transports: [], + accountCache: 10000, + storageCache: 1000, + skeletonSubchainMergeMinimum: 0, + }) const pool = new PeerPool() as any const chain = await Chain.create({ config }) const skeleton = new Skeleton({ chain, config, metaDB: new MemoryLevel() }) diff --git a/packages/client/test/sync/fetcher/storagefetcher.spec.ts b/packages/client/test/sync/fetcher/storagefetcher.spec.ts index 6cc76198c1..1f30603d9c 100644 --- a/packages/client/test/sync/fetcher/storagefetcher.spec.ts +++ b/packages/client/test/sync/fetcher/storagefetcher.spec.ts @@ -70,7 +70,7 @@ tape('[StorageFetcher]', async (t) => { }) t.test('should process', (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const pool = new PeerPool() as any const fetcher = new StorageFetcher({ config, @@ -119,7 +119,7 @@ tape('[StorageFetcher]', async (t) => { }) t.test('should adopt correctly', (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const pool = new PeerPool() as any const fetcher = new StorageFetcher({ config, @@ -168,7 +168,7 @@ tape('[StorageFetcher]', async (t) => { }) t.test('should request correctly', async (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const chain = await Chain.create({ config }) const pool = new PeerPool() as any const p = new SnapProtocol({ config, chain }) @@ -230,7 +230,7 @@ tape('[StorageFetcher]', async (t) => { }) t.test('should verify proof correctly', async (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const chain = await Chain.create({ config }) const pool = new PeerPool() as any const p = new SnapProtocol({ config, chain }) @@ -326,7 +326,7 @@ tape('[StorageFetcher]', async (t) => { }) t.test('should find a fetchable peer', async (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const pool = new PeerPool() as any const fetcher = new StorageFetcher({ config, diff --git a/packages/client/test/sync/fullsync.spec.ts b/packages/client/test/sync/fullsync.spec.ts index eb135fd22a..840d5b80fb 100644 --- a/packages/client/test/sync/fullsync.spec.ts +++ b/packages/client/test/sync/fullsync.spec.ts @@ -31,7 +31,7 @@ tape('[FullSynchronizer]', async (t) => { const { FullSynchronizer } = await import('../../lib/sync/fullsync') t.test('should initialize correctly', async (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const pool = new PeerPool() as any const chain = await Chain.create({ config }) const sync = new FullSynchronizer({ config, pool, chain, txPool, execution }) @@ -40,7 +40,7 @@ tape('[FullSynchronizer]', async (t) => { }) t.test('should open', async (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const pool = new PeerPool() as any const chain = await Chain.create({ config }) const sync = new FullSynchronizer({ @@ -60,7 +60,7 @@ tape('[FullSynchronizer]', async (t) => { }) t.test('should get height', async (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const pool = new PeerPool() as any const chain = await Chain.create({ config }) const sync = new FullSynchronizer({ config, pool, chain, txPool, execution }) @@ -75,7 +75,7 @@ tape('[FullSynchronizer]', async (t) => { }) t.test('should find best', async (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const pool = new PeerPool() as any const chain = await Chain.create({ config }) const sync = new FullSynchronizer({ @@ -109,7 +109,12 @@ tape('[FullSynchronizer]', async (t) => { t.test('should sync', async (t) => { t.plan(3) - const config = new Config({ transports: [], safeReorgDistance: 0 }) + const config = new Config({ + transports: [], + accountCache: 10000, + storageCache: 1000, + safeReorgDistance: 0, + }) const pool = new PeerPool() as any const chain = await Chain.create({ config }) const sync = new FullSynchronizer({ @@ -148,7 +153,7 @@ tape('[FullSynchronizer]', async (t) => { }) t.test('should send NewBlock/NewBlockHashes to right peers', async (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const pool = new PeerPool() as any const chain = await Chain.create({ config }) const sync = new FullSynchronizer({ diff --git a/packages/client/test/sync/lightsync.spec.ts b/packages/client/test/sync/lightsync.spec.ts index 9f5b4f5760..955f859ff6 100644 --- a/packages/client/test/sync/lightsync.spec.ts +++ b/packages/client/test/sync/lightsync.spec.ts @@ -24,7 +24,7 @@ tape('[LightSynchronizer]', async (t) => { const { LightSynchronizer } = await import('../../lib/sync/lightsync') t.test('should initialize correctly', async (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const pool = new PeerPool() as any const chain = await Chain.create({ config }) const sync = new LightSynchronizer({ config, pool, chain }) @@ -33,7 +33,7 @@ tape('[LightSynchronizer]', async (t) => { }) t.test('should find best', async (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const pool = new PeerPool() as any const chain = await Chain.create({ config }) const sync = new LightSynchronizer({ @@ -62,7 +62,12 @@ tape('[LightSynchronizer]', async (t) => { t.test('should sync', async (t) => { t.plan(3) - const config = new Config({ transports: [], safeReorgDistance: 0 }) + const config = new Config({ + transports: [], + accountCache: 10000, + storageCache: 1000, + safeReorgDistance: 0, + }) const pool = new PeerPool() as any const chain = await Chain.create({ config }) const sync = new LightSynchronizer({ @@ -99,7 +104,12 @@ tape('[LightSynchronizer]', async (t) => { t.test('import headers', async (st) => { td.reset() st.plan(1) - const config = new Config({ transports: [], safeReorgDistance: 0 }) + const config = new Config({ + transports: [], + accountCache: 10000, + storageCache: 1000, + safeReorgDistance: 0, + }) const pool = new PeerPool() as any const chain = await Chain.create({ config }) const sync = new LightSynchronizer({ @@ -133,7 +143,7 @@ tape('[LightSynchronizer]', async (t) => { t.test('sync errors', async (st) => { td.reset() st.plan(1) - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const pool = new PeerPool() as any const chain = await Chain.create({ config }) const sync = new LightSynchronizer({ diff --git a/packages/client/test/sync/skeleton.spec.ts b/packages/client/test/sync/skeleton.spec.ts index c8480b3f6a..65742d87dc 100644 --- a/packages/client/test/sync/skeleton.spec.ts +++ b/packages/client/test/sync/skeleton.spec.ts @@ -195,6 +195,8 @@ tape('[Skeleton] / initSync', async (t) => { common, transports: [], logger: getLogger({ loglevel: 'debug' }), + accountCache: 10000, + storageCache: 1000, }) const chain = await Chain.create({ config }) const skeleton = new Skeleton({ chain, config, metaDB: new MemoryLevel() }) @@ -309,6 +311,8 @@ tape('[Skeleton] / setHead', async (t) => { common, transports: [], logger: getLogger({ loglevel: 'debug' }), + accountCache: 10000, + storageCache: 1000, }) const chain = await Chain.create({ config }) const skeleton = new Skeleton({ chain, config, metaDB: new MemoryLevel() }) @@ -649,6 +653,8 @@ tape('[Skeleton] / setHead', async (t) => { const config = new Config({ transports: [], common, + accountCache: 10000, + storageCache: 1000, }) const chain = await Chain.create({ config }) ;(chain.blockchain as any)._validateBlocks = false @@ -755,6 +761,8 @@ tape('[Skeleton] / setHead', async (t) => { const config = new Config({ transports: [], common, + accountCache: 10000, + storageCache: 1000, }) const chain = await Chain.create({ config }) ;(chain.blockchain as any)._validateBlocks = false @@ -818,6 +826,8 @@ tape('[Skeleton] / setHead', async (t) => { transports: [], common, logger: getLogger({ loglevel: 'debug' }), + accountCache: 10000, + storageCache: 1000, }) const chain = await Chain.create({ config }) diff --git a/packages/client/test/sync/snapsync.spec.ts b/packages/client/test/sync/snapsync.spec.ts index f5800d4f1d..8ca66bfbd1 100644 --- a/packages/client/test/sync/snapsync.spec.ts +++ b/packages/client/test/sync/snapsync.spec.ts @@ -39,7 +39,7 @@ tape('[SnapSynchronizer]', async (t) => { const { SnapSynchronizer } = await import('../../lib/sync/snapsync') t.test('should initialize correctly', async (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const pool = new PeerPool() as any const chain = await Chain.create({ config }) const sync = new SnapSynchronizer({ config, pool, chain }) @@ -48,7 +48,7 @@ tape('[SnapSynchronizer]', async (t) => { }) t.test('should open', async (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const pool = new PeerPool() as any const chain = await Chain.create({ config }) const sync = new SnapSynchronizer({ config, pool, chain }) @@ -62,7 +62,7 @@ tape('[SnapSynchronizer]', async (t) => { }) t.test('should find best', async (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const pool = new PeerPool() as any const chain = await Chain.create({ config }) const sync = new SnapSynchronizer({ diff --git a/packages/client/test/sync/sync.spec.ts b/packages/client/test/sync/sync.spec.ts index 51d3892f6c..656347b584 100644 --- a/packages/client/test/sync/sync.spec.ts +++ b/packages/client/test/sync/sync.spec.ts @@ -27,7 +27,7 @@ tape('[Synchronizer]', async (t) => { PeerPool.prototype.close = td.func() t.test('should sync', async (t) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) config.syncTargetHeight = BigInt(1) const pool = new PeerPool() as any const chain = await Chain.create({ config }) diff --git a/packages/client/test/sync/txpool.spec.ts b/packages/client/test/sync/txpool.spec.ts index 7d46da2b27..f174186a6f 100644 --- a/packages/client/test/sync/txpool.spec.ts +++ b/packages/client/test/sync/txpool.spec.ts @@ -19,7 +19,12 @@ import { TxPool } from '../../lib/service/txpool' import type { StateManager } from '@ethereumjs/statemanager' const setup = () => { - const config = new Config({ transports: [], logger: getLogger({ loglevel: 'info' }) }) + const config = new Config({ + transports: [], + accountCache: 10000, + storageCache: 1000, + logger: getLogger({ loglevel: 'info' }), + }) const service: any = { chain: { headers: { height: BigInt(0) }, @@ -40,7 +45,7 @@ const setup = () => { } const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.London }) -const config = new Config({ transports: [] }) +const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const handleTxs = async ( txs: any[], diff --git a/packages/client/test/util/rpc.spec.ts b/packages/client/test/util/rpc.spec.ts index b58c707c01..c9d459bb12 100644 --- a/packages/client/test/util/rpc.spec.ts +++ b/packages/client/test/util/rpc.spec.ts @@ -16,7 +16,7 @@ const request = require('supertest') tape('[Util/RPC]', (t) => { t.test('should return enabled RPC servers', async (st) => { - const config = new Config({ transports: [] }) + const config = new Config({ transports: [], accountCache: 10000, storageCache: 1000 }) const client = await EthereumClient.create({ config }) const manager = new RPCManager(client, config) const { logger } = config @@ -57,7 +57,12 @@ tape('[Util/RPC]', (t) => { }) tape('[Util/RPC/Engine eth methods]', async (t) => { - const config = new Config({ transports: [], saveReceipts: true }) + const config = new Config({ + transports: [], + accountCache: 10000, + storageCache: 1000, + saveReceipts: true, + }) const client = await EthereumClient.create({ config }) const manager = new RPCManager(client, config) const { server } = createRPCServer(manager, { diff --git a/packages/evm/src/evm.ts b/packages/evm/src/evm.ts index f822b54fb9..8bfca5615d 100644 --- a/packages/evm/src/evm.ts +++ b/packages/evm/src/evm.ts @@ -1,5 +1,6 @@ import { Chain, Common, Hardfork } from '@ethereumjs/common' import { + Account, Address, AsyncEventEmitter, KECCAK256_NULL, @@ -40,7 +41,6 @@ import type { /*ExternalInterfaceFactory,*/ Log, } from './types' -import type { Account } from '@ethereumjs/util' const debug = createDebugLogger('evm:evm') const debugGas = createDebugLogger('evm:gas') @@ -348,7 +348,10 @@ export class EVM implements EVMInterface { } protected async _executeCall(message: MessageWithTo): Promise { - const account = await this.eei.getAccount(message.authcallOrigin ?? message.caller) + let account = await this.eei.getAccount(message.authcallOrigin ?? message.caller) + if (!account) { + account = new Account() + } let errorMessage // Reduce tx value from sender if (!message.delegatecall) { @@ -359,7 +362,10 @@ export class EVM implements EVMInterface { } } // Load `to` account - const toAccount = await this.eei.getAccount(message.to) + let toAccount = await this.eei.getAccount(message.to) + if (!toAccount) { + toAccount = new Account() + } // Add tx value to the `to` account if (!message.delegatecall) { try { @@ -420,7 +426,10 @@ export class EVM implements EVMInterface { } protected async _executeCreate(message: Message): Promise { - const account = await this.eei.getAccount(message.caller) + let account = await this.eei.getAccount(message.caller) + if (!account) { + account = new Account() + } // Reduce tx value from sender await this._reduceSenderBalance(account, message) @@ -447,6 +456,9 @@ export class EVM implements EVMInterface { debug(`Generated CREATE contract address ${message.to}`) } let toAccount = await this.eei.getAccount(message.to) + if (!toAccount) { + toAccount = new Account() + } // Check for collision if ( @@ -466,6 +478,7 @@ export class EVM implements EVMInterface { } } + await this.eei.putAccount(message.to, toAccount) await this.eei.clearContractStorage(message.to) const newContractEvent = { @@ -476,6 +489,9 @@ export class EVM implements EVMInterface { await this._emit('newContract', newContractEvent) toAccount = await this.eei.getAccount(message.to) + if (!toAccount) { + toAccount = new Account() + } // EIP-161 on account creation and CREATE execution if (this._common.gteHardfork(Hardfork.SpuriousDragon)) { toAccount.nonce += BigInt(1) @@ -614,11 +630,12 @@ export class EVM implements EVMInterface { if (!this._common.gteHardfork(Hardfork.Homestead)) { // Pre-Homestead behavior; put an empty contract. // This contract would be considered "DEAD" in later hard forks. - // It is thus an unnecessary default item, which we have to save to dik + // It is thus an unnecessary default item, which we have to save to disk // It does change the state root, but it only wastes storage. //await this._state.putContractCode(message.to, result.returnValue) + //const account = await this.eei.getAccount(message.to) const account = await this.eei.getAccount(message.to) - await this.eei.putAccount(message.to, account) + await this.eei.putAccount(message.to, account!) } } @@ -636,6 +653,10 @@ export class EVM implements EVMInterface { message: Message, opts: InterpreterOpts = {} ): Promise { + let contract = await this.eei.getAccount(message.to ?? Address.zero()) + if (!contract) { + contract = new Account() + } const env = { address: message.to ?? Address.zero(), caller: message.caller ?? Address.zero(), @@ -647,7 +668,7 @@ export class EVM implements EVMInterface { gasPrice: this._tx!.gasPrice, origin: this._tx!.origin ?? message.caller ?? Address.zero(), block: this._block ?? defaultBlock(), - contract: await this.eei.getAccount(message.to ?? Address.zero()), + contract, codeAddress: message.codeAddress, gasRefund: message.gasRefund, containerCode: message.containerCode, @@ -713,6 +734,9 @@ export class EVM implements EVMInterface { const value = opts.value ?? BigInt(0) if (opts.skipBalance === true) { callerAccount = await this.eei.getAccount(caller) + if (!callerAccount) { + callerAccount = new Account() + } if (callerAccount.balance < value) { // if skipBalance and balance less than value, set caller balance to `value` to ensure sufficient funds callerAccount.balance = value @@ -741,6 +765,9 @@ export class EVM implements EVMInterface { if (!callerAccount) { callerAccount = await this.eei.getAccount(message.caller) } + if (!callerAccount) { + callerAccount = new Account() + } callerAccount.nonce++ await this.eei.putAccount(message.caller, callerAccount) if (this.DEBUG) { @@ -904,7 +931,10 @@ export class EVM implements EVMInterface { if (message.salt) { addr = generateAddress2(message.caller.bytes, message.salt, message.code as Uint8Array) } else { - const acc = await this.eei.getAccount(message.caller) + let acc = await this.eei.getAccount(message.caller) + if (!acc) { + acc = new Account() + } const newNonce = acc.nonce - BigInt(1) addr = generateAddress(message.caller.bytes, bigIntToBytes(newNonce)) } @@ -938,7 +968,10 @@ export class EVM implements EVMInterface { } protected async _touchAccount(address: Address): Promise { - const account = await this.eei.getAccount(address) + let account = await this.eei.getAccount(address) + if (!account) { + account = new Account() + } return this.eei.putAccount(address, account) } diff --git a/packages/evm/src/interpreter.ts b/packages/evm/src/interpreter.ts index 1b0e563aab..e20bec2db8 100644 --- a/packages/evm/src/interpreter.ts +++ b/packages/evm/src/interpreter.ts @@ -1,5 +1,12 @@ import { ConsensusAlgorithm } from '@ethereumjs/common' -import { MAX_UINT64, bigIntToHex, bytesToBigInt, bytesToHex, intToHex } from '@ethereumjs/util' +import { + Account, + MAX_UINT64, + bigIntToHex, + bytesToBigInt, + bytesToHex, + intToHex, +} from '@ethereumjs/util' import { debug as createDebugLogger } from 'debug' import { EOF } from './eof' @@ -13,7 +20,7 @@ import type { EVM, EVMResult } from './evm' import type { AsyncOpHandler, OpHandler, Opcode } from './opcodes' import type { Block, EEIInterface, Log } from './types' import type { Common } from '@ethereumjs/common' -import type { Account, Address } from '@ethereumjs/util' +import type { Address } from '@ethereumjs/util' const debugGas = createDebugLogger('evm:eei:gas') @@ -465,7 +472,11 @@ export class Interpreter { return this._env.contract.balance } - return (await this._eei.getAccount(address)).balance + let account = await this._eei.getAccount(address) + if (!account) { + account = new Account() + } + return account.balance } /** @@ -474,6 +485,9 @@ export class Interpreter { async storageStore(key: Uint8Array, value: Uint8Array): Promise { await this._eei.storageStore(this._env.address, key, value) const account = await this._eei.getAccount(this._env.address) + if (!account) { + throw new Error('could not read account along persisting memory') + } this._env.contract = account } @@ -850,6 +864,9 @@ export class Interpreter { Object.assign(this._result.selfdestruct, selfdestruct) // update stateRoot on current contract const account = await this._eei.getAccount(this._env.address) + if (!account) { + throw new Error('could not read contract account') + } this._env.contract = account this._runState.gasRefund = results.execResult.gasRefund ?? BigInt(0) } @@ -933,6 +950,9 @@ export class Interpreter { Object.assign(this._result.selfdestruct, selfdestruct) // update stateRoot on current contract const account = await this._eei.getAccount(this._env.address) + if (!account) { + throw new Error('could not read contract account') + } this._env.contract = account this._runState.gasRefund = results.execResult.gasRefund ?? BigInt(0) if (results.createdAddress) { @@ -976,7 +996,10 @@ export class Interpreter { this._result.selfdestruct[bytesToHex(this._env.address.bytes)] = toAddress.bytes // Add to beneficiary balance - const toAccount = await this._eei.getAccount(toAddress) + let toAccount = await this._eei.getAccount(toAddress) + if (!toAccount) { + toAccount = new Account() + } toAccount.balance += this._env.contract.balance await this._eei.putAccount(toAddress, toAccount) diff --git a/packages/evm/src/opcodes/functions.ts b/packages/evm/src/opcodes/functions.ts index 656b760e81..18a327af13 100644 --- a/packages/evm/src/opcodes/functions.ts +++ b/packages/evm/src/opcodes/functions.ts @@ -515,7 +515,7 @@ export const handlers: Map = new Map([ const addressBigInt = runState.stack.pop() const address = new Address(addresstoBytes(addressBigInt)) const account = await runState.eei.getAccount(address) - if (account.isEmpty()) { + if (!account || account.isEmpty()) { runState.stack.push(BigInt(0)) return } diff --git a/packages/evm/src/opcodes/gas.ts b/packages/evm/src/opcodes/gas.ts index 3b10ea773d..4601437a19 100644 --- a/packages/evm/src/opcodes/gas.ts +++ b/packages/evm/src/opcodes/gas.ts @@ -335,7 +335,10 @@ export const dynamicGasHandlers: Map BigInt(0)) { gas += common.param('gasPrices', 'authcallValueTransfer') const account = await runState.eei.getAccount(toAddress) - if (account.isEmpty()) { + if (!account) { gas += common.param('gasPrices', 'callNewAccount') } } @@ -596,7 +599,7 @@ export const dynamicGasHandlers: Map BigInt(0)) { // This technically checks if account is empty or non-existent - const empty = (await runState.eei.getAccount(selfdestructToAddress)).isEmpty() + const empty = await runState.eei.accountIsEmptyOrNonExistent(selfdestructToAddress) if (empty) { deductGas = true } diff --git a/packages/evm/src/types.ts b/packages/evm/src/types.ts index 339e4fc7fa..454ef55975 100644 --- a/packages/evm/src/types.ts +++ b/packages/evm/src/types.ts @@ -50,6 +50,7 @@ export interface EVMStateAccess extends StateAccess { clearOriginalStorageCache(): void cleanupTouchedAccounts(): Promise generateCanonicalGenesis(initState: any): Promise + accountIsEmptyOrNonExistent(address: Address): Promise } export type DeleteOpcode = { @@ -259,9 +260,8 @@ type AccountFields = Partial - getAccount(address: Address): Promise + getAccount(address: Address): Promise putAccount(address: Address, account: Account): Promise - accountIsEmpty(address: Address): Promise deleteAccount(address: Address): Promise modifyAccountFields(address: Address, accountFields: AccountFields): Promise putContractCode(address: Address, value: Uint8Array): Promise @@ -273,7 +273,7 @@ interface StateAccess { commit(): Promise revert(): Promise getStateRoot(): Promise - setStateRoot(stateRoot: Uint8Array): Promise + setStateRoot(stateRoot: Uint8Array, clearCache?: boolean): Promise getProof?(address: Address, storageSlots: Uint8Array[]): Promise verifyProof?(proof: Proof): Promise hasStateRoot(root: Uint8Array): Promise diff --git a/packages/evm/test/eips/eip-3860.spec.ts b/packages/evm/test/eips/eip-3860.spec.ts index 93cc46f793..cf2fd84457 100644 --- a/packages/evm/test/eips/eip-3860.spec.ts +++ b/packages/evm/test/eips/eip-3860.spec.ts @@ -60,8 +60,8 @@ tape('EIP 3860 tests', (t) => { const evmWithout3860 = await EVM.create({ common: commonWithout3860, eei: eei.copy() }) const contractFactory = Address.fromString('0xb94f5374fce5edbc8e2a8697c15331677e6ebf0b') const contractAccount = await evm.eei.getAccount(contractFactory) - await evm.eei.putAccount(contractFactory, contractAccount) - await evmWithout3860.eei.putAccount(contractFactory, contractAccount) + await evm.eei.putAccount(contractFactory, contractAccount!) + await evmWithout3860.eei.putAccount(contractFactory, contractAccount!) const factoryCode = hexToBytes( '7f600a80600080396000f3000000000000000000000000000000000000000000006000526000355a8160006000f05a8203600a55806000556001600155505050' ) @@ -102,8 +102,8 @@ tape('EIP 3860 tests', (t) => { const evmWithout3860 = await EVM.create({ common: commonWithout3860, eei: eei.copy() }) const contractFactory = Address.fromString('0xb94f5374fce5edbc8e2a8697c15331677e6ebf0b') const contractAccount = await evm.eei.getAccount(contractFactory) - await evm.eei.putAccount(contractFactory, contractAccount) - await evmWithout3860.eei.putAccount(contractFactory, contractAccount) + await evm.eei.putAccount(contractFactory, contractAccount!) + await evmWithout3860.eei.putAccount(contractFactory, contractAccount!) const factoryCode = hexToBytes( '7f600a80600080396000f3000000000000000000000000000000000000000000006000526000355a60008260006000f55a8203600a55806000556001600155505050' ) @@ -177,8 +177,8 @@ tape('EIP 3860 tests', (t) => { }) const contractFactory = Address.fromString('0xb94f5374fce5edbc8e2a8697c15331677e6ebf0b') const contractAccount = await evm.eei.getAccount(contractFactory) - await evm.eei.putAccount(contractFactory, contractAccount) - await evmDisabled.eei.putAccount(contractFactory, contractAccount) + await evm.eei.putAccount(contractFactory, contractAccount!) + await evmDisabled.eei.putAccount(contractFactory, contractAccount!) // This factory code: // -> reads 32 bytes from the calldata (X) // Attempts to create a contract of X size diff --git a/packages/evm/test/runCall.spec.ts b/packages/evm/test/runCall.spec.ts index 98d4abe245..c5215ee568 100644 --- a/packages/evm/test/runCall.spec.ts +++ b/packages/evm/test/runCall.spec.ts @@ -337,11 +337,12 @@ tape('ensure that sstores pay for the right gas costs pre-byzantium', async (t) // this should thus go OOG const code = '3460005500' + await eei.putAccount(caller, new Account()) await eei.putContractCode(address, hexToBytes(code)) const account = await eei.getAccount(caller) - account.balance = BigInt(100) - await eei.putAccount(caller, account) + account!.balance = BigInt(100) + await eei.putAccount(caller, account!) /* Situation: @@ -419,8 +420,8 @@ tape( await eei.putContractCode(address, hexToBytes(code)) const account = await eei.getAccount(address) - account.nonce = MAX_UINT64 - BigInt(1) - await eei.putAccount(address, account) + account!.nonce = MAX_UINT64 - BigInt(1) + await eei.putAccount(address, account!) // setup the call arguments const runCallArgs = { @@ -461,10 +462,10 @@ tape('Ensure that IDENTITY precompile copies the memory', async (t) => { const evm = await EVM.create({ common, eei }) const code = '3034526020600760203460045afa602034343e604034f3' - const account = await eei.getAccount(caller) - account.nonce = BigInt(1) // ensure nonce for contract is correct - account.balance = BigInt(10000000000000000) - await eei.putAccount(caller, account) + const account = new Account() + account!.nonce = BigInt(1) // ensure nonce for contract is correct + account!.balance = BigInt(10000000000000000) + await eei.putAccount(caller, account!) // setup the call arguments const runCallArgs = { @@ -533,7 +534,7 @@ tape('runCall() -> skipBalance behavior', async (t) => { await eei.modifyAccountFields(sender, { nonce: BigInt(0), balance }) const res = await evm.runCall(runCallArgs) t.pass('runCall should not throw with no balance and skipBalance') - const senderBalance = (await eei.getAccount(sender)).balance + const senderBalance = (await eei.getAccount(sender))!.balance t.equal( senderBalance, balance ?? BigInt(0), diff --git a/packages/evm/test/runCode.spec.ts b/packages/evm/test/runCode.spec.ts index 93502fe1fd..60fb632396 100644 --- a/packages/evm/test/runCode.spec.ts +++ b/packages/evm/test/runCode.spec.ts @@ -1,3 +1,4 @@ +import { Account, Address } from '@ethereumjs/util' import { hexToBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' @@ -80,6 +81,8 @@ tape('VM.runCode: interpreter', (t) => { t.test('should throw on non-EvmError', async (st) => { const eei = await getEEI() + const address = Address.fromString(`0x${'00'.repeat(20)}`) + await eei.putAccount(address, new Account()) eei.putContractStorage = (..._args) => { throw new Error('Test') } diff --git a/packages/statemanager/package.json b/packages/statemanager/package.json index 78893ccfb0..d039f4f07c 100644 --- a/packages/statemanager/package.json +++ b/packages/statemanager/package.json @@ -37,7 +37,7 @@ "tape": "tape -r ts-node/register", "test": "npm run test:node && npm run test:browser", "test:browser": "karma start karma.conf.js", - "test:node": "npm run tape -- test/*.spec.ts", + "test:node": "npm run tape -- 'test/**/*.spec.ts'", "tsc": "../../config/cli/ts-compile.sh" }, "dependencies": { @@ -46,7 +46,8 @@ "debug": "^4.3.3", "ethereum-cryptography": "^1.1.2", "ethers": "^5.7.1", - "js-sdsl": "^4.1.4" + "js-sdsl": "^4.1.4", + "lru-cache": "^7.18.3" }, "devDependencies": { "@ethereumjs/block": "^4.2.1", diff --git a/packages/statemanager/src/baseStateManager.ts b/packages/statemanager/src/baseStateManager.ts deleted file mode 100644 index 778be20e1c..0000000000 --- a/packages/statemanager/src/baseStateManager.ts +++ /dev/null @@ -1,142 +0,0 @@ -import { debug as createDebugLogger } from 'debug' - -import type { Cache } from './cache' -import type { AccountFields } from './interface' -import type { DefaultStateManagerOpts } from './stateManager' -import type { Account, Address } from '@ethereumjs/util' -import type { Debugger } from 'debug' - -/** - * Abstract BaseStateManager class for the non-storage-backend - * related functionality parts of a StateManager like keeping - * track of accessed storage (`EIP-2929`) or touched accounts - * (`EIP-158`). - * - * This is not a full StateManager implementation in itself but - * can be used to ease implementing an own StateManager. - * - * Note that the implementation is pretty new (October 2021) - * and we cannot guarantee a stable interface yet. - */ -export abstract class BaseStateManager { - _debug: Debugger - _cache!: Cache - - /** - * StateManager is run in DEBUG mode (default: false) - * Taken from DEBUG environment variable - * - * Safeguards on debug() calls are added for - * performance reasons to avoid string literal evaluation - * @hidden - */ - protected readonly DEBUG: boolean = false - - /** - * Needs to be called from the subclass constructor - */ - constructor(_opts: DefaultStateManagerOpts) { - // Skip DEBUG calls unless 'ethjs' included in environmental DEBUG variables - this.DEBUG = process?.env?.DEBUG?.includes('ethjs') ?? false - - this._debug = createDebugLogger('statemanager:statemanager') - } - - /** - * Gets the account associated with `address`. Returns an empty account if the account does not exist. - * @param address - Address of the `account` to get - */ - async getAccount(address: Address): Promise { - const account = await this._cache.getOrLoad(address) - return account - } - - /** - * Saves an account into state under the provided `address`. - * @param address - Address under which to store `account` - * @param account - The account to store - */ - async putAccount(address: Address, account: Account): Promise { - if (this.DEBUG) { - this._debug( - `Save account address=${address} nonce=${account.nonce} balance=${ - account.balance - } contract=${account.isContract() ? 'yes' : 'no'} empty=${account.isEmpty() ? 'yes' : 'no'}` - ) - } - this._cache.put(address, account) - } - - /** - * Gets the account associated with `address`, modifies the given account - * fields, then saves the account into state. Account fields can include - * `nonce`, `balance`, `storageRoot`, and `codeHash`. - * @param address - Address of the account to modify - * @param accountFields - Object containing account fields and values to modify - */ - async modifyAccountFields(address: Address, accountFields: AccountFields): Promise { - const account = await this.getAccount(address) - account.nonce = accountFields.nonce ?? account.nonce - account.balance = accountFields.balance ?? account.balance - account.storageRoot = accountFields.storageRoot ?? account.storageRoot - account.codeHash = accountFields.codeHash ?? account.codeHash - await this.putAccount(address, account) - } - - /** - * Deletes an account from state under the provided `address`. The account will also be removed from the state trie. - * @param address - Address of the account which should be deleted - */ - async deleteAccount(address: Address) { - if (this.DEBUG) { - this._debug(`Delete account ${address}`) - } - this._cache.del(address) - } - - async accountIsEmpty(address: Address): Promise { - const account = await this.getAccount(address) - return account.isEmpty() - } - - abstract putContractCode(address: Address, value: Uint8Array): Promise - abstract getContractStorage(address: Address, key: Uint8Array): Promise - abstract putContractStorage(address: Address, key: Uint8Array, value: Uint8Array): Promise - - /** - * Checkpoints the current state of the StateManager instance. - * State changes that follow can then be committed by calling - * `commit` or `reverted` by calling rollback. - * - * Partial implementation, called from the subclass. - */ - async checkpoint(): Promise { - this._cache.checkpoint() - } - - /** - * Commits the current change-set to the instance since the - * last call to checkpoint. - * - * Partial implementation, called from the subclass. - */ - async commit(): Promise { - // setup cache checkpointing - this._cache.commit() - } - - /** - * Reverts the current change-set to the instance since the - * last call to checkpoint. - * - * Partial implementation , called from the subclass. - */ - async revert(): Promise { - // setup cache checkpointing - this._cache.revert() - } - - async flush(): Promise { - await this._cache.flush() - } -} diff --git a/packages/statemanager/src/cache.ts b/packages/statemanager/src/cache.ts deleted file mode 100644 index 8cd0607d3e..0000000000 --- a/packages/statemanager/src/cache.ts +++ /dev/null @@ -1,192 +0,0 @@ -import { Account, bytesToHex, hexStringToBytes } from '@ethereumjs/util' -import { OrderedMap } from 'js-sdsl' - -import type { Address } from '@ethereumjs/util' -import type { OrderedMapIterator } from 'js-sdsl' - -export type getCb = (address: Address) => Promise -export type putCb = (keyBuf: Uint8Array, accountRlp: Uint8Array) => Promise -export type deleteCb = (keyBuf: Uint8Array) => Promise - -export interface CacheOpts { - getCb: getCb - putCb: putCb - deleteCb: deleteCb -} - -/** - * @ignore - */ -export class Cache { - _cache: OrderedMap - _cacheEnd: OrderedMapIterator - _checkpoints: any[] - - _getCb: getCb - _putCb: putCb - _deleteCb: deleteCb - - constructor(opts: CacheOpts) { - this._cache = new OrderedMap() - this._cacheEnd = this._cache.end() - this._getCb = opts.getCb - this._putCb = opts.putCb - this._deleteCb = opts.deleteCb - this._checkpoints = [] - } - - /** - * Puts account to cache under its address. - * @param key - Address of account - * @param val - Account - */ - put(key: Address, val: Account, fromTrie: boolean = false): void { - const modified = !fromTrie - this._update(key, val, modified, false) - } - - /** - * Returns the queried account or an empty account. - * @param key - Address of account - */ - get(key: Address): Account { - const account = this.lookup(key) - return account ?? new Account() - } - - /** - * Returns the queried account or undefined. - * @param key - Address of account - */ - lookup(key: Address): Account | undefined { - const keyStr = bytesToHex(key.bytes) - - const it = this._cache.find(keyStr) - if (!it.equals(this._cacheEnd)) { - const value = it.pointer[1] - const rlp = value.val - const account = Account.fromRlpSerializedAccount(rlp) - ;(account as any).virtual = value.virtual - return account - } - } - - /** - * Returns true if the key was deleted and thus existed in the cache earlier - * @param key - trie key to lookup - */ - keyIsDeleted(key: Address): boolean { - const keyStr = bytesToHex(key.bytes) - const it = this._cache.find(keyStr) - if (!it.equals(this._cacheEnd)) { - return it.pointer[1].deleted - } - return false - } - - /** - * Looks up address in cache, if not found, looks it up - * in the underlying trie. - * @param key - Address of account - */ - async getOrLoad(address: Address): Promise { - let account = this.lookup(address) - - if (!account) { - account = await this._getCb(address) - if (account) { - this._update(address, account, false, false, false) - } else { - account = new Account() - ;(account as any).virtual = true - this._update(address, account, false, false, true) - } - } - - return account - } - - /** - * Flushes cache by updating accounts that have been modified - * and removing accounts that have been deleted. - */ - async flush(): Promise { - const it = this._cache.begin() - while (!it.equals(this._cacheEnd)) { - const value = it.pointer[1] - if (value.modified === true) { - value.modified = false - const keyBuf = hexStringToBytes(it.pointer[0]) - if (value.deleted === false) { - const accountRlp = value.val - await this._putCb(keyBuf, accountRlp) - } else { - value.deleted = true - value.virtual = true - value.val = new Account().serialize() - await this._deleteCb(keyBuf) - } - } - it.next() - } - } - - /** - * Marks current state of cache as checkpoint, which can - * later on be reverted or committed. - */ - checkpoint(): void { - this._checkpoints.push(new OrderedMap(this._cache)) - } - - /** - * Revert changes to cache last checkpoint (no effect on trie). - */ - revert(): void { - this._cache = this._checkpoints.pop() - this._cacheEnd = this._cache.end() - } - - /** - * Commits to current state of cache (no effect on trie). - */ - commit(): void { - this._checkpoints.pop() - } - - /** - * Clears cache. - */ - clear(): void { - this._cache.clear() - } - - /** - * Marks address as deleted in cache. - * @param key - Address - */ - del(key: Address): void { - this._update(key, new Account(), true, true, true) - } - - /** - * Generic cache update helper function - * - * @param key - * @param value - * @param modified - Has the value been modified or is it coming unchanged from the trie (also used for deleted accounts) - * @param deleted - Delete operation on an account - * @param virtual - Account doesn't exist in the underlying trie - */ - _update( - key: Address, - value: Account, - modified: boolean, - deleted: boolean, - virtual = false - ): void { - const keyHex = bytesToHex(key.bytes) - const val = value.serialize() - this._cache.setElement(keyHex, { val, modified, deleted, virtual }) - } -} diff --git a/packages/statemanager/src/cache/account.ts b/packages/statemanager/src/cache/account.ts new file mode 100644 index 0000000000..1d535b55a6 --- /dev/null +++ b/packages/statemanager/src/cache/account.ts @@ -0,0 +1,276 @@ +import { bytesToHex } from '@ethereumjs/util' +import { debug as createDebugLogger } from 'debug' +import { OrderedMap } from 'js-sdsl' + +import { Cache } from './cache' +import { CacheType } from './types' + +import type { CacheOpts } from './types' +import type { Account, Address } from '@ethereumjs/util' +import type LRUCache from 'lru-cache' + +const LRU = require('lru-cache') + +/** + * account: undefined + * + * Account is known to not exist in the trie + */ +type AccountCacheElement = { + accountRLP: Uint8Array | undefined +} + +export class AccountCache extends Cache { + _lruCache: LRUCache | undefined + _orderedMapCache: OrderedMap | undefined + + /** + * Diff cache collecting the state of the cache + * at the beginning of checkpoint height + * (respectively: before a first modification) + * + * If the whole cache element is undefined (in contrast + * to the account), the element didn't exist in the cache + * before. + */ + _diffCache: OrderedMap[] = [] + + constructor(opts: CacheOpts) { + super() + if (opts.type === CacheType.LRU) { + this._lruCache = new LRU({ + max: opts.size, + updateAgeOnGet: true, + }) + } else { + this._orderedMapCache = new OrderedMap() + } + + this._diffCache.push(new OrderedMap()) + this._debug = createDebugLogger('statemanager:cache:account') + } + + _saveCachePreState(cacheKeyHex: string) { + const it = this._diffCache[this._checkpoints].find(cacheKeyHex) + if (it.equals(this._diffCache[this._checkpoints].end())) { + let oldElem: AccountCacheElement | undefined + if (this._lruCache) { + oldElem = this._lruCache!.get(cacheKeyHex) + } else { + oldElem = this._orderedMapCache!.getElementByKey(cacheKeyHex) + } + this._diffCache[this._checkpoints].setElement(cacheKeyHex, oldElem) + } + } + + /** + * Puts account to cache under its address. + * @param key - Address of account or undefined if account doesn't exist in the trie + * @param val - Account + */ + put(address: Address, account: Account | undefined): void { + const addressHex = bytesToHex(address.bytes) + this._saveCachePreState(addressHex) + const elem = { + accountRLP: account !== undefined ? account.serialize() : undefined, + } + + if (this.DEBUG) { + this._debug(`Put account ${addressHex}`) + } + if (this._lruCache) { + this._lruCache!.set(addressHex, elem) + } else { + this._orderedMapCache!.setElement(addressHex, elem) + } + this._stats.writes += 1 + } + + /** + * Returns the queried account or undefined if account doesn't exist + * @param key - Address of account + */ + get(address: Address): AccountCacheElement | undefined { + const addressHex = bytesToHex(address.bytes) + if (this.DEBUG) { + this._debug(`Get account ${addressHex}`) + } + + let elem: AccountCacheElement | undefined + if (this._lruCache) { + elem = this._lruCache!.get(addressHex) + } else { + elem = this._orderedMapCache!.getElementByKey(addressHex) + } + this._stats.reads += 1 + if (elem) { + this._stats.hits += 1 + } + return elem + } + + /** + * Marks address as deleted in cache. + * @param key - Address + */ + del(address: Address): void { + const addressHex = bytesToHex(address.bytes) + this._saveCachePreState(addressHex) + if (this.DEBUG) { + this._debug(`Delete account ${addressHex}`) + } + if (this._lruCache) { + this._lruCache!.set(addressHex, { + accountRLP: undefined, + }) + } else { + this._orderedMapCache!.setElement(addressHex, { + accountRLP: undefined, + }) + } + + this._stats.dels += 1 + } + + /** + * Flushes cache by returning accounts that have been modified + * or deleted and resetting the diff cache (at checkpoint height). + */ + flush(): [string, AccountCacheElement][] { + if (this.DEBUG) { + this._debug(`Flushing cache on checkpoint ${this._checkpoints}`) + } + + const diffMap = this._diffCache[this._checkpoints]! + const it = diffMap.begin() + + const items: [string, AccountCacheElement][] = [] + + while (!it.equals(diffMap.end())) { + const cacheKeyHex = it.pointer[0] + let elem: AccountCacheElement | undefined + if (this._lruCache) { + elem = this._lruCache!.get(cacheKeyHex) + } else { + elem = this._orderedMapCache!.getElementByKey(cacheKeyHex) + } + + if (elem !== undefined) { + items.push([cacheKeyHex, elem]) + } + it.next() + } + this._diffCache[this._checkpoints] = new OrderedMap() + return items + } + + /** + * Revert changes to cache last checkpoint (no effect on trie). + */ + revert(): void { + this._checkpoints -= 1 + if (this.DEBUG) { + this._debug(`Revert to checkpoint ${this._checkpoints}`) + } + const diffMap = this._diffCache.pop()! + + const it = diffMap.begin() + while (!it.equals(diffMap.end())) { + const addressHex = it.pointer[0] + const elem = it.pointer[1] + if (elem === undefined) { + if (this._lruCache) { + this._lruCache!.delete(addressHex) + } else { + this._orderedMapCache!.eraseElementByKey(addressHex) + } + } else { + if (this._lruCache) { + this._lruCache!.set(addressHex, elem) + } else { + this._orderedMapCache!.setElement(addressHex, elem) + } + } + it.next() + } + } + + /** + * Commits to current state of cache (no effect on trie). + */ + commit(): void { + this._checkpoints -= 1 + if (this.DEBUG) { + this._debug(`Commit to checkpoint ${this._checkpoints}`) + } + const diffMap = this._diffCache.pop()! + + const it = diffMap.begin() + while (!it.equals(diffMap.end())) { + const addressHex = it.pointer[0] + const element = it.pointer[1] + const oldElem = this._diffCache[this._checkpoints].getElementByKey(addressHex) + if (oldElem === undefined) { + this._diffCache[this._checkpoints].setElement(addressHex, element) + } + it.next() + } + } + + /** + * Marks current state of cache as checkpoint, which can + * later on be reverted or committed. + */ + checkpoint(): void { + this._checkpoints += 1 + if (this.DEBUG) { + this._debug(`New checkpoint ${this._checkpoints}`) + } + this._diffCache.push(new OrderedMap()) + } + + /** + * Returns the size of the cache + * @returns + */ + size() { + if (this._lruCache) { + return this._lruCache!.size + } else { + return this._orderedMapCache!.size() + } + } + + /** + * Returns a dict with cache stats + * @param reset + */ + stats(reset = true) { + const stats = { ...this._stats } + stats.size = this.size() + if (reset) { + this._stats = { + size: 0, + reads: 0, + hits: 0, + writes: 0, + dels: 0, + } + } + return stats + } + + /** + * Clears cache. + */ + clear(): void { + if (this.DEBUG) { + this._debug(`Clear cache`) + } + if (this._lruCache) { + this._lruCache!.clear() + } else { + this._orderedMapCache!.clear() + } + } +} diff --git a/packages/statemanager/src/cache/cache.ts b/packages/statemanager/src/cache/cache.ts new file mode 100644 index 0000000000..f3db4c364f --- /dev/null +++ b/packages/statemanager/src/cache/cache.ts @@ -0,0 +1,34 @@ +import { debug as createDebugLogger } from 'debug' + +import type { Debugger } from 'debug' + +export class Cache { + _debug: Debugger + + _checkpoints = 0 + + _stats = { + size: 0, + reads: 0, + hits: 0, + writes: 0, + dels: 0, + } + + /** + * StateManager cache is run in DEBUG mode (default: false) + * Taken from DEBUG environment variable + * + * Safeguards on debug() calls are added for + * performance reasons to avoid string literal evaluation + * @hidden + */ + protected readonly DEBUG: boolean = false + + constructor() { + // Skip DEBUG calls unless 'ethjs' included in environmental DEBUG variables + this.DEBUG = process?.env?.DEBUG?.includes('ethjs') ?? false + + this._debug = createDebugLogger('statemanager:cache') + } +} diff --git a/packages/statemanager/src/cache/index.ts b/packages/statemanager/src/cache/index.ts new file mode 100644 index 0000000000..1991354d69 --- /dev/null +++ b/packages/statemanager/src/cache/index.ts @@ -0,0 +1,3 @@ +export * from './account' +export * from './storage' +export * from './types' diff --git a/packages/statemanager/src/cache/storage.ts b/packages/statemanager/src/cache/storage.ts new file mode 100644 index 0000000000..30e6f335cb --- /dev/null +++ b/packages/statemanager/src/cache/storage.ts @@ -0,0 +1,374 @@ +import { bytesToHex, hexStringToBytes } from '@ethereumjs/util' +import { debug as createDebugLogger } from 'debug' +import { OrderedMap } from 'js-sdsl' + +import { Cache } from './cache' +import { CacheType } from './types' + +import type { CacheOpts } from './types' +import type { Address } from '@ethereumjs/util' +import type LRUCache from 'lru-cache' + +const LRU = require('lru-cache') + +/** + * key -> storage mapping + * + * undefined: storage value is known not to exist in the cache + */ +type DiffStorageCacheMap = OrderedMap +type StorageCacheMap = OrderedMap + +export class StorageCache extends Cache { + _lruCache: LRUCache | undefined + _orderedMapCache: OrderedMap | undefined + + /** + * Diff cache collecting the state of the cache + * at the beginning of checkpoint height + * (respectively: before a first modification) + * + * If the whole cache element is undefined (in contrast + * to the account), the element didn't exist in the cache + * before. + */ + _diffCache: OrderedMap[] = [] + + constructor(opts: CacheOpts) { + super() + if (opts.type === CacheType.LRU) { + this._lruCache = new LRU({ + max: opts.size, + updateAgeOnGet: true, + }) + } else { + this._orderedMapCache = new OrderedMap() + } + + this._diffCache.push(new OrderedMap()) + + if (this.DEBUG) { + this._debug = createDebugLogger('statemanager:cache:storage') + } + } + + _saveCachePreState(addressHex: string, keyHex: string) { + const itAddress = this._diffCache[this._checkpoints].find(addressHex) + let diffStorageMap: DiffStorageCacheMap + if (itAddress.equals(this._diffCache[this._checkpoints].end())) { + diffStorageMap = new OrderedMap() + } else { + diffStorageMap = itAddress.pointer[1] + } + + const itKey = diffStorageMap.find(keyHex) + if (itKey.equals(diffStorageMap.end())) { + let oldStorageMap: StorageCacheMap | undefined + let oldStorage: Uint8Array | undefined = undefined + if (this._lruCache) { + oldStorageMap = this._lruCache!.get(addressHex) + if (oldStorageMap) { + oldStorage = oldStorageMap.getElementByKey(keyHex) + } + } else { + oldStorageMap = this._orderedMapCache!.getElementByKey(addressHex) + if (oldStorageMap) { + oldStorage = oldStorageMap.getElementByKey(keyHex) + } + } + if (oldStorage === undefined) { + oldStorage = hexStringToBytes('80') + } + diffStorageMap.setElement(keyHex, oldStorage) + this._diffCache[this._checkpoints].setElement(addressHex, diffStorageMap) + } + } + + /** + * Puts storage value to cache under address_key cache key. + * @param address - Account address + * @param key - Storage key + * @param val - RLP-encoded storage value + */ + put(address: Address, key: Uint8Array, value: Uint8Array): void { + const addressHex = bytesToHex(address.bytes) + const keyHex = bytesToHex(key) + this._saveCachePreState(addressHex, keyHex) + + if (this.DEBUG) { + this._debug( + `Put storage for ${addressHex}: ${keyHex} -> ${ + value !== undefined ? bytesToHex(value) : '' + }` + ) + } + if (this._lruCache) { + let storageMap = this._lruCache!.get(addressHex) + if (!storageMap) { + storageMap = new OrderedMap() + } + storageMap.setElement(keyHex, value) + this._lruCache!.set(addressHex, storageMap) + } else { + let storageMap = this._orderedMapCache!.getElementByKey(addressHex) + if (!storageMap) { + storageMap = new OrderedMap() + } + storageMap.setElement(keyHex, value) + this._orderedMapCache!.setElement(addressHex, storageMap) + } + this._stats.writes += 1 + } + + /** + * Returns the queried slot as the RLP encoded storage value + * hexStringToBytes('80'): slot is known to be empty + * undefined: slot is not in cache + * @param key - Address of account + */ + get(address: Address, key: Uint8Array): Uint8Array | undefined { + const addressHex = bytesToHex(address.bytes) + const keyHex = bytesToHex(key) + if (this.DEBUG) { + this._debug(`Get storage for ${addressHex}`) + } + + let storageMap: StorageCacheMap | undefined + if (this._lruCache) { + storageMap = this._lruCache!.get(addressHex) + } else { + storageMap = this._orderedMapCache!.getElementByKey(addressHex) + } + this._stats.reads += 1 + if (storageMap) { + this._stats.hits += 1 + return storageMap.getElementByKey(keyHex) + } + } + + /** + * Marks storage key for address as deleted in cache. + * @param address - Address + * @param key - Storage key + */ + del(address: Address, key: Uint8Array): void { + const addressHex = bytesToHex(address.bytes) + const keyHex = bytesToHex(key) + this._saveCachePreState(addressHex, keyHex) + if (this.DEBUG) { + this._debug(`Delete storage for ${addressHex}: ${keyHex}`) + } + if (this._lruCache) { + let storageMap = this._lruCache!.get(addressHex) + if (!storageMap) { + storageMap = new OrderedMap() + } + storageMap.setElement(keyHex, hexStringToBytes('80')) + this._lruCache!.set(addressHex, storageMap) + } else { + let storageMap = this._orderedMapCache!.getElementByKey(addressHex) + if (!storageMap) { + storageMap = new OrderedMap() + } + storageMap.setElement(keyHex, hexStringToBytes('80')) + this._orderedMapCache!.setElement(addressHex, storageMap) + } + + this._stats.dels += 1 + } + + /** + * Deletes all storage slots for address from the cache + * @param address + */ + clearContractStorage(address: Address): void { + const addressHex = bytesToHex(address.bytes) + if (this._lruCache) { + this._lruCache!.set(addressHex, new OrderedMap()) + } else { + this._orderedMapCache!.setElement(addressHex, new OrderedMap()) + } + } + + /** + * Flushes cache by returning storage slots that have been modified + * or deleted and resetting the diff cache (at checkpoint height). + */ + flush(): [string, string, Uint8Array | undefined][] { + if (this.DEBUG) { + this._debug(`Flushing cache on checkpoint ${this._checkpoints}`) + } + + const diffMap = this._diffCache[this._checkpoints]! + const it = diffMap.begin() + + const items: [string, string, Uint8Array | undefined][] = [] + + while (!it.equals(diffMap.end())) { + const addressHex = it.pointer[0] + const diffStorageMap = it.pointer[1] + let storageMap: StorageCacheMap | undefined + if (this._lruCache) { + storageMap = this._lruCache!.get(addressHex) + } else { + storageMap = this._orderedMapCache!.getElementByKey(addressHex) + } + + if (storageMap !== undefined) { + const itDiffStorage = diffStorageMap.begin() + while (!itDiffStorage.equals(diffStorageMap.end())) { + const keyHex = itDiffStorage.pointer[0] + const value = storageMap.getElementByKey(keyHex) + items.push([addressHex, keyHex, value]) + itDiffStorage.next() + } + } else { + throw new Error('Inconsistent cache state') + } + it.next() + } + this._diffCache[this._checkpoints] = new OrderedMap() + return items + } + + /** + * Revert changes to cache last checkpoint (no effect on trie). + */ + revert(): void { + this._checkpoints -= 1 + if (this.DEBUG) { + this._debug(`Revert to checkpoint ${this._checkpoints}`) + } + const diffMap = this._diffCache.pop()! + + const it = diffMap.begin() + while (!it.equals(diffMap.end())) { + const addressHex = it.pointer[0] + const diffStorageMap = it.pointer[1] + + const itStorage = diffStorageMap.begin() + while (!itStorage.equals(diffStorageMap.end())) { + const keyHex = itStorage.pointer[0] + const value = itStorage.pointer[1] + if (this._lruCache) { + const storageMap = this._lruCache.get(addressHex) ?? new OrderedMap() + if (value === undefined) { + // Value is known not to be in the cache before + // -> delete from cache + storageMap.eraseElementByKey(keyHex) + } else { + // Value is known to be in the cache before + // (being either some storage value or the RLP-encoded empty Uint8Array) + storageMap.setElement(keyHex, value) + } + this._lruCache.set(addressHex, storageMap) + } else { + const storageMap = this._orderedMapCache!.getElementByKey(addressHex) ?? new OrderedMap() + if (!value) { + storageMap.eraseElementByKey(keyHex) + } else { + storageMap.setElement(keyHex, value) + } + this._orderedMapCache!.setElement(addressHex, storageMap) + } + itStorage.next() + } + it.next() + } + } + + /** + * Commits to current state of cache (no effect on trie). + */ + commit(): void { + this._checkpoints -= 1 + if (this.DEBUG) { + this._debug(`Commit to checkpoint ${this._checkpoints}`) + } + const higherHeightDiffMap = this._diffCache.pop()! + const lowerHeightDiffMap = this._diffCache[this._checkpoints] + + const it = higherHeightDiffMap.begin() + // Go through diffMap from the pre-commit checkpoint height. + // 1. Iterate through all state pre states + // 2. If state pre-state is not in the new (lower) height diff map, take pre commit pre state value + // 3. If state is in new map, take this one, since this superseeds subsequent changes + while (!it.equals(higherHeightDiffMap.end())) { + const addressHex = it.pointer[0] + const higherHeightStorageDiff = it.pointer[1] + + const itHigherHeightStorageDiff = higherHeightStorageDiff.begin() + const lowerHeightStorageDiff = + lowerHeightDiffMap.getElementByKey(addressHex) ?? new OrderedMap() + + while (!itHigherHeightStorageDiff.equals(higherHeightStorageDiff.end())) { + const keyHex = itHigherHeightStorageDiff.pointer[0] + const value = itHigherHeightStorageDiff.pointer[1] + const lowerHeightDiffStorage = lowerHeightStorageDiff.getElementByKey(keyHex) + if (lowerHeightDiffStorage === undefined) { + lowerHeightStorageDiff.setElement(keyHex, value) + } + itHigherHeightStorageDiff.next() + } + lowerHeightDiffMap.setElement(addressHex, lowerHeightStorageDiff) + it.next() + } + } + + /** + * Marks current state of cache as checkpoint, which can + * later on be reverted or committed. + */ + checkpoint(): void { + this._checkpoints += 1 + if (this.DEBUG) { + this._debug(`New checkpoint ${this._checkpoints}`) + } + this._diffCache.push(new OrderedMap()) + } + + /** + * Returns the size of the cache + * @returns + */ + size() { + if (this._lruCache) { + return this._lruCache!.size + } else { + return this._orderedMapCache!.size() + } + } + + /** + * Returns a dict with cache stats + * @param reset + */ + stats(reset = true) { + const stats = { ...this._stats } + stats.size = this.size() + if (reset) { + this._stats = { + size: 0, + reads: 0, + hits: 0, + writes: 0, + dels: 0, + } + } + return stats + } + + /** + * Clears cache. + */ + clear(): void { + if (this.DEBUG) { + this._debug(`Clear cache`) + } + if (this._lruCache) { + this._lruCache!.clear() + } else { + this._orderedMapCache!.clear() + } + } +} diff --git a/packages/statemanager/src/cache/types.ts b/packages/statemanager/src/cache/types.ts new file mode 100644 index 0000000000..0e5b3d40f6 --- /dev/null +++ b/packages/statemanager/src/cache/types.ts @@ -0,0 +1,9 @@ +export enum CacheType { + LRU = 'lru', + ORDERED_MAP = 'ordered_map', +} + +export interface CacheOpts { + size: number + type: CacheType +} diff --git a/packages/statemanager/src/ethersStateManager.ts b/packages/statemanager/src/ethersStateManager.ts index 80c825bf9d..5194d942f1 100644 --- a/packages/statemanager/src/ethersStateManager.ts +++ b/packages/statemanager/src/ethersStateManager.ts @@ -4,13 +4,10 @@ import { debug } from 'debug' import { keccak256 } from 'ethereum-cryptography/keccak' import { ethers } from 'ethers' -import { Cache } from './cache' - -import { BaseStateManager } from '.' +import { AccountCache, CacheType } from './cache' import type { Proof, StateManager } from '.' -import type { getCb, putCb } from './cache' -import type { StorageDump } from './interface' +import type { AccountFields, StorageDump } from './interface' import type { Address } from '@ethereumjs/util' const log = debug('statemanager') @@ -20,15 +17,14 @@ export interface EthersStateManagerOpts { blockTag: bigint | 'earliest' } -export class EthersStateManager extends BaseStateManager implements StateManager { +export class EthersStateManager implements StateManager { private provider: ethers.providers.StaticJsonRpcProvider | ethers.providers.JsonRpcProvider private contractCache: Map private storageCache: Map> private blockTag: string - _cache: Cache + _accountCache: AccountCache constructor(opts: EthersStateManagerOpts) { - super({}) if (typeof opts.provider === 'string') { this.provider = new ethers.providers.StaticJsonRpcProvider(opts.provider) } else if (opts.provider instanceof ethers.providers.JsonRpcProvider) { @@ -42,16 +38,7 @@ export class EthersStateManager extends BaseStateManager implements StateManager this.contractCache = new Map() this.storageCache = new Map() - const getCb: getCb = async (address) => { - return this.getAccountFromProvider(address) - } - const putCb: putCb = async (_keyBuf, _accountRlp) => { - return Promise.resolve() - } - const deleteCb = async (_keyBuf: Uint8Array) => { - return Promise.resolve() - } - this._cache = new Cache({ getCb, putCb, deleteCb }) + this._accountCache = new AccountCache({ size: 100000, type: CacheType.LRU }) } copy(): EthersStateManager { @@ -61,7 +48,7 @@ export class EthersStateManager extends BaseStateManager implements StateManager }) ;(newState as any).contractCache = new Map(this.contractCache) ;(newState as any).storageCache = new Map(this.storageCache) - ;(newState as any)._cache = this._cache + ;(newState as any)._accountCache = this._accountCache return newState } @@ -72,17 +59,17 @@ export class EthersStateManager extends BaseStateManager implements StateManager */ setBlockTag(blockTag: bigint | 'earliest'): void { this.blockTag = blockTag === 'earliest' ? blockTag : bigIntToHex(blockTag) - this.clearCache() + this.clearCaches() } /** * Clears the internal cache so all accounts, contract code, and storage slots will * initially be retrieved from the provider */ - clearCache(): void { + clearCaches(): void { this.contractCache.clear() this.storageCache.clear() - this._cache.clear() + this._accountCache.clear() } /** @@ -196,8 +183,8 @@ export class EthersStateManager extends BaseStateManager implements StateManager async accountExists(address: Address): Promise { log(`Verify if ${address.toString()} exists`) - const localAccount = this._cache.get(address) - if (!localAccount.isEmpty()) return true + const localAccount = this._accountCache.get(address) + if (localAccount !== undefined) return true // Get merkle proof for `address` from provider const proof = await this.provider.send('eth_getProof', [address.toString(), [], this.blockTag]) @@ -215,9 +202,17 @@ export class EthersStateManager extends BaseStateManager implements StateManager * @returns {Promise} - Resolves with the code corresponding to the provided address. * Returns an empty `Uint8Array` if the account has no associated code. */ - async getAccount(address: Address): Promise { - const account = this._cache.getOrLoad(address) + async getAccount(address: Address): Promise { + const elem = this._accountCache?.get(address) + if (elem !== undefined) { + return elem.accountRLP !== undefined + ? Account.fromRlpSerializedAccount(elem.accountRLP) + : undefined + } + const rlp = (await this.getAccountFromProvider(address)).serialize() + const account = rlp !== null ? Account.fromRlpSerializedAccount(rlp) : undefined + this._accountCache?.put(address, account) return account } @@ -247,7 +242,34 @@ export class EthersStateManager extends BaseStateManager implements StateManager * @param account - The account to store */ async putAccount(address: Address, account: Account): Promise { - this._cache.put(address, account) + this._accountCache.put(address, account) + } + + /** + * Gets the account associated with `address`, modifies the given account + * fields, then saves the account into state. Account fields can include + * `nonce`, `balance`, `storageRoot`, and `codeHash`. + * @param address - Address of the account to modify + * @param accountFields - Object containing account fields and values to modify + */ + async modifyAccountFields(address: Address, accountFields: AccountFields): Promise { + let account = await this.getAccount(address) + if (!account) { + account = new Account() + } + account.nonce = accountFields.nonce ?? account.nonce + account.balance = accountFields.balance ?? account.balance + account.storageRoot = accountFields.storageRoot ?? account.storageRoot + account.codeHash = accountFields.codeHash ?? account.codeHash + await this.putAccount(address, account) + } + + /** + * Deletes an account from state under the provided `address`. + * @param address - Address of the account which should be deleted + */ + async deleteAccount(address: Address) { + this._accountCache.del(address) } /** @@ -274,7 +296,7 @@ export class EthersStateManager extends BaseStateManager implements StateManager * Partial implementation, called from the subclass. */ async checkpoint(): Promise { - this._cache.checkpoint() + this._accountCache.checkpoint() } /** @@ -285,7 +307,7 @@ export class EthersStateManager extends BaseStateManager implements StateManager */ async commit(): Promise { // setup cache checkpointing - this._cache.commit() + this._accountCache.commit() } /** @@ -296,11 +318,11 @@ export class EthersStateManager extends BaseStateManager implements StateManager */ async revert(): Promise { // setup cache checkpointing - this._cache.revert() + this._accountCache.revert() } async flush(): Promise { - await this._cache.flush() + this._accountCache.flush() } /** diff --git a/packages/statemanager/src/index.ts b/packages/statemanager/src/index.ts index 04d1675d98..30083415e3 100644 --- a/packages/statemanager/src/index.ts +++ b/packages/statemanager/src/index.ts @@ -1,4 +1,4 @@ -export { BaseStateManager } from './baseStateManager' -export { EthersStateManager, EthersStateManagerOpts } from './ethersStateManager' -export { AccountFields, StateAccess, StateManager } from './interface' -export { CODEHASH_PREFIX, DefaultStateManager, Proof } from './stateManager' +export * from './cache' +export * from './ethersStateManager' +export * from './interface' +export * from './stateManager' diff --git a/packages/statemanager/src/interface.ts b/packages/statemanager/src/interface.ts index b7353515cd..747f630d22 100644 --- a/packages/statemanager/src/interface.ts +++ b/packages/statemanager/src/interface.ts @@ -12,9 +12,8 @@ export type AccountFields = Partial - getAccount(address: Address): Promise - putAccount(address: Address, account: Account): Promise - accountIsEmpty(address: Address): Promise + getAccount(address: Address): Promise + putAccount(address: Address, account: Account | undefined): Promise deleteAccount(address: Address): Promise modifyAccountFields(address: Address, accountFields: AccountFields): Promise putContractCode(address: Address, value: Uint8Array): Promise @@ -26,7 +25,7 @@ export interface StateAccess { commit(): Promise revert(): Promise getStateRoot(): Promise - setStateRoot(stateRoot: Uint8Array): Promise + setStateRoot(stateRoot: Uint8Array, clearCache?: boolean): Promise getProof?(address: Address, storageSlots: Uint8Array[]): Promise verifyProof?(proof: Proof): Promise hasStateRoot(root: Uint8Array): Promise @@ -36,4 +35,5 @@ export interface StateManager extends StateAccess { copy(): StateManager flush(): Promise dumpStorage(address: Address): Promise + clearCaches(): void } diff --git a/packages/statemanager/src/stateManager.ts b/packages/statemanager/src/stateManager.ts index ff7f4bab35..b02ef62305 100644 --- a/packages/statemanager/src/stateManager.ts +++ b/packages/statemanager/src/stateManager.ts @@ -2,8 +2,11 @@ import { RLP } from '@ethereumjs/rlp' import { Trie } from '@ethereumjs/trie' import { Account, + Address, KECCAK256_NULL, + KECCAK256_NULL_S, KECCAK256_RLP, + KECCAK256_RLP_S, bigIntToHex, bytesToHex, bytesToPrefixedHexString, @@ -15,14 +18,15 @@ import { unpadBytes, utf8ToBytes, } from '@ethereumjs/util' +import { debug as createDebugLogger } from 'debug' import { keccak256 } from 'ethereum-cryptography/keccak' +import { hexToBytes } from 'ethereum-cryptography/utils' -import { BaseStateManager } from './baseStateManager' -import { Cache } from './cache' +import { AccountCache, CacheType, StorageCache } from './cache' -import type { getCb, putCb } from './cache' -import type { StateManager, StorageDump } from './interface' -import type { Address, PrefixedHexString } from '@ethereumjs/util' +import type { AccountFields, StateManager, StorageDump } from './interface' +import type { PrefixedHexString } from '@ethereumjs/util' +import type { Debugger } from 'debug' export type StorageProof = { key: PrefixedHexString @@ -40,6 +44,49 @@ export type Proof = { storageProof: StorageProof[] } +type CacheOptions = { + /** + * Allows for cache deactivation + * + * Depending on the use case and underlying datastore (and eventual concurrent cache + * mechanisms there), usage with or without cache can be faster + * + * Default: false + */ + deactivate?: boolean + + /** + * Cache type to use. + * + * Available options: + * + * ORDERED_MAP: Cache with no fixed upper bound and dynamic allocation, + * use for dynamic setups like testing or similar. + * + * LRU: LRU cache with pre-allocation of memory and a fixed size. + * Use for larger and more persistent caches. + */ + type?: CacheType + + /** + * Size of the cache (only for LRU cache) + * + * Default: 100000 (account cache) / 20000 (storage cache) + * + * Note: the cache/trie interplay mechanism is designed in a way that + * the theoretical number of max modified accounts between two flush operations + * should be smaller than the cache size, otherwise the cache will "forget" the + * old modifications resulting in an incomplete set of trie-flushed accounts. + */ + size?: number +} + +type CacheSettings = { + deactivate: boolean + type: CacheType + size: number +} + /** * Prefix to distinguish between a contract deployed with code `0x80` * and `RLP([])` (also having the value `0x80`). @@ -65,6 +112,10 @@ export interface DefaultStateManagerOpts { * E.g. by putting the code `0x80` into the empty trie, will lead to a corrupted trie. */ prefixCodeHashes?: boolean + + accountCacheOpts?: CacheOptions + + storageCacheOpts?: CacheOptions } /** @@ -77,53 +128,159 @@ export interface DefaultStateManagerOpts { * The default state manager implementation uses a * `@ethereumjs/trie` trie as a data backend. */ -export class DefaultStateManager extends BaseStateManager implements StateManager { +export class DefaultStateManager implements StateManager { + _debug: Debugger + _accountCache?: AccountCache + _storageCache?: StorageCache + _trie: Trie _storageTries: { [key: string]: Trie } + _codeCache: { [key: string]: Uint8Array } + + protected readonly _prefixCodeHashes: boolean + protected readonly _accountCacheSettings: CacheSettings + protected readonly _storageCacheSettings: CacheSettings - private readonly _prefixCodeHashes: boolean + /** + * StateManager is run in DEBUG mode (default: false) + * Taken from DEBUG environment variable + * + * Safeguards on debug() calls are added for + * performance reasons to avoid string literal evaluation + * @hidden + */ + protected readonly DEBUG: boolean = false /** * Instantiate the StateManager interface. */ constructor(opts: DefaultStateManagerOpts = {}) { - super(opts) + // Skip DEBUG calls unless 'ethjs' included in environmental DEBUG variables + this.DEBUG = process?.env?.DEBUG?.includes('ethjs') ?? false + + this._debug = createDebugLogger('statemanager:statemanager') this._trie = opts.trie ?? new Trie({ useKeyHashing: true }) this._storageTries = {} + this._codeCache = {} this._prefixCodeHashes = opts.prefixCodeHashes ?? true + this._accountCacheSettings = { + deactivate: opts.accountCacheOpts?.deactivate ?? false, + type: opts.accountCacheOpts?.type ?? CacheType.ORDERED_MAP, + size: opts.accountCacheOpts?.size ?? 100000, + } - /* - * For a custom StateManager implementation adopt these - * callbacks passed to the `Cache` instantiated to perform - * the `get`, `put` and `delete` operations with the - * desired backend. - */ - const getCb: getCb = async (address) => { - const rlp = await this._trie.get(address.bytes) - return rlp ? Account.fromRlpSerializedAccount(rlp) : undefined - } - const putCb: putCb = async (keyBuf, accountRlp) => { - const trie = this._trie - await trie.put(keyBuf, accountRlp) + if (!this._accountCacheSettings.deactivate) { + this._accountCache = new AccountCache({ + size: this._accountCacheSettings.size, + type: this._accountCacheSettings.type, + }) + } + + this._storageCacheSettings = { + deactivate: opts.storageCacheOpts?.deactivate ?? false, + type: opts.storageCacheOpts?.type ?? CacheType.ORDERED_MAP, + size: opts.storageCacheOpts?.size ?? 20000, + } + + if (!this._storageCacheSettings.deactivate) { + this._storageCache = new StorageCache({ + size: this._storageCacheSettings.size, + type: this._storageCacheSettings.type, + }) } - const deleteCb = async (keyBuf: Uint8Array) => { + } + + /** + * Gets the account associated with `address` or `undefined` if account does not exist + * @param address - Address of the `account` to get + */ + async getAccount(address: Address): Promise { + if (!this._accountCacheSettings.deactivate) { + const elem = this._accountCache!.get(address) + if (elem !== undefined) { + return elem.accountRLP !== undefined + ? Account.fromRlpSerializedAccount(elem.accountRLP) + : undefined + } + } + + const rlp = await this._trie.get(address.bytes) + const account = rlp !== null ? Account.fromRlpSerializedAccount(rlp) : undefined + if (this.DEBUG) { + this._debug(`Get account ${address} from DB (${account ? 'exists' : 'non-existent'})`) + } + this._accountCache?.put(address, account) + return account + } + + /** + * Saves an account into state under the provided `address`. + * @param address - Address under which to store `account` + * @param account - The account to store or undefined if to be deleted + */ + async putAccount(address: Address, account: Account | undefined): Promise { + if (this.DEBUG) { + this._debug( + `Save account address=${address} nonce=${account?.nonce} balance=${ + account?.balance + } contract=${account && account.isContract() ? 'yes' : 'no'} empty=${ + account && account.isEmpty() ? 'yes' : 'no' + }` + ) + } + if (this._accountCacheSettings.deactivate) { const trie = this._trie - await trie.del(keyBuf) + if (account !== undefined) { + await trie.put(address.bytes, account.serialize()) + } else { + await trie.del(address.bytes) + } + } else { + if (account !== undefined) { + this._accountCache!.put(address, account) + } else { + this._accountCache!.del(address) + } } - this._cache = new Cache({ getCb, putCb, deleteCb }) } /** - * Copies the current instance of the `StateManager` - * at the last fully committed point, i.e. as if all current - * checkpoints were reverted. + * Gets the account associated with `address`, modifies the given account + * fields, then saves the account into state. Account fields can include + * `nonce`, `balance`, `storageRoot`, and `codeHash`. + * @param address - Address of the account to modify + * @param accountFields - Object containing account fields and values to modify */ - copy(): StateManager { - return new DefaultStateManager({ - trie: this._trie.copy(false), - }) + async modifyAccountFields(address: Address, accountFields: AccountFields): Promise { + let account = await this.getAccount(address) + if (!account) { + account = new Account() + } + account.nonce = accountFields.nonce ?? account.nonce + account.balance = accountFields.balance ?? account.balance + account.storageRoot = accountFields.storageRoot ?? account.storageRoot + account.codeHash = accountFields.codeHash ?? account.codeHash + await this.putAccount(address, account) + } + + /** + * Deletes an account from state under the provided `address`. + * @param address - Address of the account which should be deleted + */ + async deleteAccount(address: Address) { + if (this.DEBUG) { + this._debug(`Delete account ${address}`) + } + if (this._accountCacheSettings.deactivate) { + await this._trie.del(address.bytes) + } else { + this._accountCache!.del(address) + } + if (!this._storageCacheSettings.deactivate) { + this._storageCache?.clearContractStorage(address) + } } /** @@ -143,9 +300,15 @@ export class DefaultStateManager extends BaseStateManager implements StateManage // @ts-expect-error await this._trie._db.put(key, value) + const keyHex = bytesToHex(key) + this._codeCache[keyHex] = value + if (this.DEBUG) { this._debug(`Update codeHash (-> ${short(codeHash)}) for account ${address}`) } + if (!(await this.getAccount(address))) { + await this.putAccount(address, new Account()) + } await this.modifyAccountFields(address, { codeHash }) } @@ -157,29 +320,26 @@ export class DefaultStateManager extends BaseStateManager implements StateManage */ async getContractCode(address: Address): Promise { const account = await this.getAccount(address) + if (!account) { + return new Uint8Array(0) + } if (!account.isContract()) { return new Uint8Array(0) } const key = this._prefixCodeHashes ? concatBytes(CODEHASH_PREFIX, account.codeHash) : account.codeHash - // @ts-expect-error - const code = await this._trie._db.get(key) - return code ?? new Uint8Array(0) - } - /** - * Creates a storage trie from the primary storage trie - * for an account and saves this in the storage cache. - * @private - */ - async _lookupStorageTrie(address: Address): Promise { - // from state trie - const account = await this.getAccount(address) - const storageTrie = this._trie.copy(false) - storageTrie.root(account.storageRoot) - storageTrie.flushCheckpoints() - return storageTrie + const keyHex = bytesToHex(key) + if (keyHex in this._codeCache) { + return this._codeCache[keyHex] + } else { + // `db` is a protected member of the `trie` class so telling Typescript to expect this error to avoid casting `db` to `any` + // @ts-expect-error + const code = (await this._trie._db.get(key)) ?? new Uint8Array(0) + this._codeCache[keyHex] = code + return code + } } /** @@ -187,13 +347,15 @@ export class DefaultStateManager extends BaseStateManager implements StateManage * cache or does a lookup. * @private */ - async _getStorageTrie(address: Address): Promise { + async _getStorageTrie(address: Address, account: Account): Promise { // from storage cache const addressHex = bytesToHex(address.bytes) - let storageTrie = this._storageTries[addressHex] - if (storageTrie === undefined || storageTrie === null) { - // lookup from state - storageTrie = await this._lookupStorageTrie(address) + const storageTrie = this._storageTries[addressHex] + if (storageTrie === undefined) { + const storageTrie = this._trie.copy(false) + storageTrie.root(account.storageRoot) + storageTrie.flushCheckpoints() + return storageTrie } return storageTrie } @@ -203,7 +365,7 @@ export class DefaultStateManager extends BaseStateManager implements StateManage * the shortest representation of the stored value. * @param address - Address of the account to get the storage for * @param key - Key in the account's storage to get the value for. Must be 32 bytes long. - * @returns {Promise} - The storage value for the account + * @returns - The storage value for the account * corresponding to the provided address at the provided key. * If this does not exist an empty `Uint8Array` is returned. */ @@ -211,9 +373,23 @@ export class DefaultStateManager extends BaseStateManager implements StateManage if (key.length !== 32) { throw new Error('Storage key must be 32 bytes long') } + if (!this._storageCacheSettings.deactivate) { + const value = this._storageCache!.get(address, key) + if (value !== undefined) { + const decoded = RLP.decode(value ?? new Uint8Array(0)) as Uint8Array + return decoded + } + } - const trie = await this._getStorageTrie(address) + const account = await this.getAccount(address) + if (!account) { + throw new Error('getContractStorage() called on non-existing account') + } + const trie = await this._getStorageTrie(address, account) const value = await trie.get(key) + if (!this._storageCacheSettings.deactivate) { + this._storageCache?.put(address, key, value ?? hexStringToBytes('80')) + } const decoded = RLP.decode(value ?? new Uint8Array(0)) as Uint8Array return decoded } @@ -226,11 +402,12 @@ export class DefaultStateManager extends BaseStateManager implements StateManage */ async _modifyContractStorage( address: Address, + account: Account, modifyTrie: (storageTrie: Trie, done: Function) => void ): Promise { // eslint-disable-next-line no-async-promise-executor return new Promise(async (resolve) => { - const storageTrie = await this._getStorageTrie(address) + const storageTrie = await this._getStorageTrie(address, account) modifyTrie(storageTrie, async () => { // update storage cache @@ -238,34 +415,20 @@ export class DefaultStateManager extends BaseStateManager implements StateManage this._storageTries[addressHex] = storageTrie // update contract storageRoot - const contract = this._cache.get(address) - contract.storageRoot = storageTrie.root() - - await this.putAccount(address, contract) + account.storageRoot = storageTrie.root() + await this.putAccount(address, account) resolve() }) }) } - /** - * Adds value to the state trie for the `account` - * corresponding to `address` at the provided `key`. - * @param address - Address to set a storage value for - * @param key - Key to set the value at. Must be 32 bytes long. - * @param value - Value to set at `key` for account corresponding to `address`. Cannot be more than 32 bytes. Leading zeros are stripped. If it is a empty or filled with zeros, deletes the value. - */ - async putContractStorage(address: Address, key: Uint8Array, value: Uint8Array): Promise { - if (key.length !== 32) { - throw new Error('Storage key must be 32 bytes long') - } - - if (value.length > 32) { - throw new Error('Storage value cannot be longer than 32 bytes') - } - - value = unpadBytes(value) - - await this._modifyContractStorage(address, async (storageTrie, done) => { + async _writeContractStorage( + address: Address, + account: Account, + key: Uint8Array, + value: Uint8Array + ) { + await this._modifyContractStorage(address, account, async (storageTrie, done) => { if (value instanceof Uint8Array && value.length) { // format input const encodedValue = RLP.encode(value) @@ -284,12 +447,49 @@ export class DefaultStateManager extends BaseStateManager implements StateManage }) } + /** + * Adds value to the state trie for the `account` + * corresponding to `address` at the provided `key`. + * @param address - Address to set a storage value for + * @param key - Key to set the value at. Must be 32 bytes long. + * @param value - Value to set at `key` for account corresponding to `address`. + * Cannot be more than 32 bytes. Leading zeros are stripped. + * If it is a empty or filled with zeros, deletes the value. + */ + async putContractStorage(address: Address, key: Uint8Array, value: Uint8Array): Promise { + if (key.length !== 32) { + throw new Error('Storage key must be 32 bytes long') + } + + if (value.length > 32) { + throw new Error('Storage value cannot be longer than 32 bytes') + } + + const account = await this.getAccount(address) + if (!account) { + throw new Error('putContractStorage() called on non-existing account') + } + + value = unpadBytes(value) + if (!this._storageCacheSettings.deactivate) { + const encodedValue = RLP.encode(value) + this._storageCache!.put(address, key, encodedValue) + } else { + await this._writeContractStorage(address, account, key, value) + } + } + /** * Clears all storage entries for the account corresponding to `address`. * @param address - Address to clear the storage of */ async clearContractStorage(address: Address): Promise { - await this._modifyContractStorage(address, (storageTrie, done) => { + const account = await this.getAccount(address) + if (!account) { + throw new Error(`clearContractStorage() called on non-existing account (${address})`) + } + this._storageCache?.clearContractStorage(address) + await this._modifyContractStorage(address, account, (storageTrie, done) => { storageTrie.root(storageTrie.EMPTY_TRIE_ROOT) done() }) @@ -302,7 +502,8 @@ export class DefaultStateManager extends BaseStateManager implements StateManage */ async checkpoint(): Promise { this._trie.checkpoint() - await super.checkpoint() + this._storageCache?.checkpoint() + this._accountCache?.checkpoint() } /** @@ -312,7 +513,8 @@ export class DefaultStateManager extends BaseStateManager implements StateManage async commit(): Promise { // setup trie checkpointing await this._trie.commit() - await super.commit() + this._storageCache?.commit() + this._accountCache?.commit() } /** @@ -322,8 +524,46 @@ export class DefaultStateManager extends BaseStateManager implements StateManage async revert(): Promise { // setup trie checkpointing await this._trie.revert() + this._storageCache?.revert() + this._accountCache?.revert() this._storageTries = {} - await super.revert() + this._codeCache = {} + } + + /** + * Writes all cache items to the trie + */ + async flush(): Promise { + if (!this._storageCacheSettings.deactivate) { + const items = this._storageCache!.flush() + for (const item of items) { + const address = Address.fromString(`0x${item[0]}`) + const keyHex = item[1] + const keyBytes = hexToBytes(keyHex) + const value = item[2] + + const decoded = RLP.decode(value ?? new Uint8Array(0)) as Uint8Array + const account = await this.getAccount(address) + if (account) { + await this._writeContractStorage(address, account, keyBytes, decoded) + } + } + } + if (!this._accountCacheSettings.deactivate) { + const items = this._accountCache!.flush() + for (const item of items) { + const addressHex = item[0] + const addressBytes = hexToBytes(addressHex) + const elem = item[1] + if (elem.accountRLP === undefined) { + const trie = this._trie + await trie.del(addressBytes) + } else { + const trie = this._trie + await trie.put(addressBytes, elem.accountRLP) + } + } + } } /** @@ -333,23 +573,35 @@ export class DefaultStateManager extends BaseStateManager implements StateManage */ async getProof(address: Address, storageSlots: Uint8Array[] = []): Promise { const account = await this.getAccount(address) + if (!account) { + // throw new Error(`getProof() can only be called for an existing account`) + const returnValue: Proof = { + address: address.toString(), + balance: '0x', + codeHash: '0x' + KECCAK256_NULL_S, + nonce: '0x', + storageHash: '0x' + KECCAK256_RLP_S, + accountProof: (await this._trie.createProof(address.bytes)).map((p) => + bytesToPrefixedHexString(p) + ), + storageProof: [], + } + return returnValue + } const accountProof: PrefixedHexString[] = (await this._trie.createProof(address.bytes)).map( (p) => bytesToPrefixedHexString(p) ) const storageProof: StorageProof[] = [] - const storageTrie = await this._getStorageTrie(address) + const storageTrie = await this._getStorageTrie(address, account) for (const storageKey of storageSlots) { const proof = (await storageTrie.createProof(storageKey)).map((p) => bytesToPrefixedHexString(p) ) - let value = bytesToPrefixedHexString(await this.getContractStorage(address, storageKey)) - if (value === '0x') { - value = '0x0' - } + const value = bytesToPrefixedHexString(await this.getContractStorage(address, storageKey)) const proofItem: StorageProof = { key: bytesToPrefixedHexString(storageKey), - value, + value: value === '0x' ? '0x0' : value, // Return '0x' values as '0x0' since this is a JSON RPC response proof, } storageProof.push(proofItem) @@ -386,7 +638,6 @@ export class DefaultStateManager extends BaseStateManager implements StateManage // Verify that the account is empty in the proof. const emptyBytes = new Uint8Array(0) const notEmptyErrorMsg = 'Invalid proof provided: account is not empty' - const nonce = unpadBytes(hexStringToBytes(proof.nonce)) if (!equalsBytes(nonce, emptyBytes)) { throw new Error(`${notEmptyErrorMsg} (nonce is not zero)`) @@ -450,7 +701,7 @@ export class DefaultStateManager extends BaseStateManager implements StateManage * @returns {Promise} - Returns the state-root of the `StateManager` */ async getStateRoot(): Promise { - await this._cache.flush() + await this.flush() return this._trie.root() } @@ -461,8 +712,8 @@ export class DefaultStateManager extends BaseStateManager implements StateManage * the state trie. * @param stateRoot - The state-root to reset the instance to */ - async setStateRoot(stateRoot: Uint8Array): Promise { - await this._cache.flush() + async setStateRoot(stateRoot: Uint8Array, clearCache: boolean = true): Promise { + await this.flush() if (!equalsBytes(stateRoot, this._trie.EMPTY_TRIE_ROOT)) { const hasRoot = await this._trie.checkRoot(stateRoot) @@ -472,8 +723,14 @@ export class DefaultStateManager extends BaseStateManager implements StateManage } this._trie.root(stateRoot) - this._cache.clear() + if (this._accountCache !== undefined && clearCache) { + this._accountCache.clear() + } + if (this._storageCache !== undefined && clearCache) { + this._storageCache.clear() + } this._storageTries = {} + this._codeCache = {} } /** @@ -484,8 +741,14 @@ export class DefaultStateManager extends BaseStateManager implements StateManage * Both are represented as hex strings without the `0x` prefix. */ async dumpStorage(address: Address): Promise { + await this.flush() + const account = await this.getAccount(address) + if (!account) { + throw new Error(`dumpStorage f() can only be called for an existing account`) + } + return new Promise((resolve, reject) => { - this._getStorageTrie(address) + this._getStorageTrie(address, account) .then((trie) => { const storage: StorageDump = {} const stream = trie.createReadStream() @@ -516,17 +779,33 @@ export class DefaultStateManager extends BaseStateManager implements StateManage * @param address - Address of the `account` to check */ async accountExists(address: Address): Promise { - const account = this._cache.lookup(address) - if ( - account && - ((account as any).virtual === undefined || (account as any).virtual === false) && - !this._cache.keyIsDeleted(address) - ) { - return true - } - if (await this._trie.get(address.bytes)) { + const account = await this.getAccount(address) + if (account) { return true + } else { + return false } - return false + } + + /** + * Copies the current instance of the `StateManager` + * at the last fully committed point, i.e. as if all current + * checkpoints were reverted. + */ + copy(): StateManager { + return new DefaultStateManager({ + trie: this._trie.copy(false), + prefixCodeHashes: this._prefixCodeHashes, + accountCacheOpts: this._accountCacheSettings, + storageCacheOpts: this._storageCacheSettings, + }) + } + + /** + * Clears all underlying caches + */ + clearCaches() { + this._accountCache?.clear() + this._storageCache?.clear() } } diff --git a/packages/statemanager/test/cache.spec.ts b/packages/statemanager/test/cache.spec.ts deleted file mode 100644 index ff761023d4..0000000000 --- a/packages/statemanager/test/cache.spec.ts +++ /dev/null @@ -1,141 +0,0 @@ -import { Trie } from '@ethereumjs/trie' -import { Account, Address, hexStringToBytes } from '@ethereumjs/util' -import * as tape from 'tape' - -import { Cache } from '../src/cache' - -import { createAccount } from './util' - -import type { getCb, putCb } from '../src/cache' - -tape('cache initialization', (t) => { - t.test('should initialize', async (st) => { - const trie = new Trie({ useKeyHashing: true }) - const getCb: getCb = async (address) => { - const innerTrie = trie - const rlp = await innerTrie.get(address.bytes) - return rlp ? Account.fromRlpSerializedAccount(rlp) : undefined - } - const putCb: putCb = async (keyBuf, accountRlp) => { - const innerTrie = trie - await innerTrie.put(keyBuf, accountRlp) - } - const deleteCb = async (keyBuf: Uint8Array) => { - const innerTrie = trie - await innerTrie.del(keyBuf) - } - const cache = new Cache({ getCb, putCb, deleteCb }) - - st.equal(cache._checkpoints.length, 0, 'initializes given trie') - st.end() - }) -}) - -tape('cache put and get account', (t) => { - const trie = new Trie({ useKeyHashing: true }) - const getCb: getCb = async (address) => { - const innerTrie = trie - const rlp = await innerTrie.get(address.bytes) - return rlp ? Account.fromRlpSerializedAccount(rlp) : undefined - } - const putCb: putCb = async (keyBuf, accountRlp) => { - const innerTrie = trie - await innerTrie.put(keyBuf, accountRlp) - } - const deleteCb = async (keyBuf: Uint8Array) => { - const innerTrie = trie - await innerTrie.del(keyBuf) - } - const cache = new Cache({ getCb, putCb, deleteCb }) - - const addr = new Address(hexStringToBytes('cd2a3d9f938e13cd947ec05abc7fe734df8dd826')) - const acc = createAccount(BigInt(0), BigInt(0xff11)) - - t.test('should fail to get non-existent account', async (st) => { - const res = cache.get(addr) - st.notEqual(res.balance, acc.balance) - st.end() - }) - - t.test('should put account', async (st) => { - cache.put(addr, acc) - const res = cache.get(addr) - st.equal(res.balance, acc.balance) - st.end() - }) - - t.test('should not have flushed to trie', async (st) => { - const res = await trie.get(addr.bytes) - st.notOk(res) - st.end() - }) - - t.test('should flush to trie', async (st) => { - await cache.flush() - st.end() - }) - - t.test('trie should contain flushed account', async (st) => { - const raw = await trie.get(addr.bytes) - const res = Account.fromRlpSerializedAccount(raw!) - st.equal(res.balance, acc.balance) - st.end() - }) - - t.test('should delete account from cache', async (st) => { - cache.del(addr) - - const res = cache.get(addr) - st.notEqual(res.balance, acc.balance) - st.end() - }) - - t.test('should update loaded account and flush it', async (st) => { - const updatedAcc = createAccount(BigInt(0), BigInt(0xff00)) - cache.put(addr, updatedAcc) - await cache.flush() - - const raw = await trie.get(addr.bytes) - const res = Account.fromRlpSerializedAccount(raw!) - st.equal(res.balance, updatedAcc.balance) - st.end() - }) -}) - -tape('cache checkpointing', (t) => { - const trie = new Trie({ useKeyHashing: true }) - const getCb: getCb = async (address) => { - const innerTrie = trie - const rlp = await innerTrie.get(address.bytes) - return rlp ? Account.fromRlpSerializedAccount(rlp) : undefined - } - const putCb: putCb = async (keyBuf, accountRlp) => { - const innerTrie = trie - await innerTrie.put(keyBuf, accountRlp) - } - const deleteCb = async (keyBuf: Uint8Array) => { - const innerTrie = trie - await innerTrie.del(keyBuf) - } - const cache = new Cache({ getCb, putCb, deleteCb }) - - const addr = new Address(hexStringToBytes('cd2a3d9f938e13cd947ec05abc7fe734df8dd826')) - const acc = createAccount(BigInt(0), BigInt(0xff11)) - const updatedAcc = createAccount(BigInt(0x00), BigInt(0xff00)) - - t.test('should revert to correct state', async (st) => { - cache.put(addr, acc) - cache.checkpoint() - cache.put(addr, updatedAcc) - - let res = cache.get(addr) - st.equal(res.balance, updatedAcc.balance) - - cache.revert() - - res = cache.get(addr) - st.equal(res.balance, acc.balance) - - st.end() - }) -}) diff --git a/packages/statemanager/test/cache/account.spec.ts b/packages/statemanager/test/cache/account.spec.ts new file mode 100644 index 0000000000..bd8554f99c --- /dev/null +++ b/packages/statemanager/test/cache/account.spec.ts @@ -0,0 +1,90 @@ +import { Address, equalsBytes, hexStringToBytes } from '@ethereumjs/util' +import * as tape from 'tape' + +import { AccountCache, CacheType } from '../../src/cache' +import { createAccount } from '../util' + +import type { Account } from '@ethereumjs/util' + +tape('Account Cache: initialization', (t) => { + t.test('should initialize', async (st) => { + const cache = new AccountCache({ size: 100, type: CacheType.LRU }) + + st.equal(cache._checkpoints, 0, 'initializes given trie') + st.end() + }) +}) + +tape('Account Cache: put and get account', (t) => { + const cache = new AccountCache({ size: 100, type: CacheType.LRU }) + + const addr = new Address(hexStringToBytes('10'.repeat(20))) + const acc: Account = createAccount(BigInt(1), BigInt(0xff11)) + const accRLP = acc.serialize() + + t.test( + 'should return undefined for CacheElement if account not present in the cache', + async (st) => { + const elem = cache.get(addr) + st.ok(elem === undefined) + st.end() + } + ) + + t.test('should put account', async (st) => { + cache.put(addr, acc) + const elem = cache.get(addr) + st.ok(elem !== undefined && elem.accountRLP && equalsBytes(elem.accountRLP, accRLP)) + st.end() + }) + + t.test('should flush', async (st) => { + const items = cache.flush() + st.equal(items.length, 1) + st.end() + }) + + t.test('should delete account from cache', async (st) => { + cache.del(addr) + + const elem = cache.get(addr) + st.ok(elem !== undefined && elem.accountRLP === undefined) + st.end() + }) +}) + +tape('Account Cache: checkpointing', (t) => { + const cache = new AccountCache({ size: 100, type: CacheType.LRU }) + + const addr = new Address(hexStringToBytes('10'.repeat(20))) + const acc = createAccount(BigInt(1), BigInt(0xff11)) + const accRLP = acc.serialize() + + const updatedAcc = createAccount(BigInt(0x00), BigInt(0xff00)) + const updatedAccRLP = updatedAcc.serialize() + + t.test('should revert to correct state', async (st) => { + cache.put(addr, acc) + cache.checkpoint() + cache.put(addr, updatedAcc) + + let elem = cache.get(addr) + st.ok(elem !== undefined && elem.accountRLP && equalsBytes(elem.accountRLP, updatedAccRLP)) + + cache.revert() + + elem = cache.get(addr) + st.ok(elem !== undefined && elem.accountRLP && equalsBytes(elem.accountRLP, accRLP)) + + st.end() + }) + + t.test('cache clearing', async (st) => { + const cache = new AccountCache({ size: 100, type: CacheType.LRU }) + cache.put(addr, acc) + cache.clear() + st.equal(cache.size(), 0, 'should delete cache objects with clear=true') + + st.end() + }) +}) diff --git a/packages/statemanager/test/cache/storage.spec.ts b/packages/statemanager/test/cache/storage.spec.ts new file mode 100644 index 0000000000..1581c75782 --- /dev/null +++ b/packages/statemanager/test/cache/storage.spec.ts @@ -0,0 +1,87 @@ +import { Address } from '@ethereumjs/util' +import { equalsBytes, hexToBytes } from 'ethereum-cryptography/utils' +import * as tape from 'tape' + +import { CacheType, StorageCache } from '../../src/cache' + +tape('Storage Cache: initialization', (t) => { + t.test('should initialize', async (st) => { + const cache = new StorageCache({ size: 100, type: CacheType.LRU }) + + st.equal(cache._checkpoints, 0, 'initializes given trie') + st.end() + }) +}) + +tape('Storage Cache: put and get account', (t) => { + const cache = new StorageCache({ size: 100, type: CacheType.LRU }) + + const addr = new Address(hexToBytes('10'.repeat(20))) + const key = hexToBytes('01') + const value = hexToBytes('01') + + t.test( + 'should return undefined for CacheElement if account not present in the cache', + async (st) => { + const elem = cache.get(addr, key) + st.ok(elem === undefined) + st.end() + } + ) + + t.test('should put storage value', async (st) => { + cache.put(addr, key, value) + const elem = cache.get(addr, key) + st.ok(elem !== undefined && equalsBytes(elem, value)) + st.end() + }) + + t.test('should flush', async (st) => { + const items = cache.flush() + st.equal(items.length, 1) + st.end() + }) + + t.test('should delete storage value from cache', async (st) => { + cache.del(addr, key) + + const elem = cache.get(addr, key) + st.ok(elem !== undefined && equalsBytes(elem, hexToBytes('80'))) + st.end() + }) +}) + +tape('Storage Cache: checkpointing', (t) => { + const cache = new StorageCache({ size: 100, type: CacheType.LRU }) + + const addr = new Address(hexToBytes('10'.repeat(20))) + const key = hexToBytes('01') + const value = hexToBytes('01') + + const updatedValue = hexToBytes('02') + + t.test('should revert to correct state', async (st) => { + cache.put(addr, key, value) + cache.checkpoint() + cache.put(addr, key, updatedValue) + + let elem = cache.get(addr, key) + st.ok(elem !== undefined && equalsBytes(elem, updatedValue)) + + cache.revert() + + elem = cache.get(addr, key) + st.ok(elem !== undefined && equalsBytes(elem, value)) + + st.end() + }) + + t.test('cache clearing', async (st) => { + const cache = new StorageCache({ size: 100, type: CacheType.LRU }) + cache.put(addr, key, value) + cache.clear() + st.equal(cache.size(), 0, 'should delete cache objects with clear=true') + + st.end() + }) +}) diff --git a/packages/statemanager/test/checkpointing.account.spec.ts b/packages/statemanager/test/checkpointing.account.spec.ts new file mode 100644 index 0000000000..53b4828c63 --- /dev/null +++ b/packages/statemanager/test/checkpointing.account.spec.ts @@ -0,0 +1,310 @@ +import { Account, Address, hexStringToBytes } from '@ethereumjs/util' +import * as tape from 'tape' + +import { DefaultStateManager } from '../src' + +tape('StateManager -> Account Checkpointing', (t) => { + const address = new Address(hexStringToBytes('11'.repeat(20))) + const account = Account.fromAccountData({ + nonce: 1, + }) + const account2 = Account.fromAccountData({ + nonce: 2, + }) + const account3 = Account.fromAccountData({ + nonce: 3, + }) + const account4 = Account.fromAccountData({ + nonce: 4, + }) + const account5 = Account.fromAccountData({ + nonce: 5, + }) + + t.test('No CP -> A1 -> Flush() (-> A1)', async (st) => { + const sm = new DefaultStateManager() + + await sm.putAccount(address, account) + await sm.flush() + st.equal((await sm.getAccount(address))!.nonce, 1n) + + sm.clearCaches() + st.equal((await sm.getAccount(address))!.nonce, 1n) + + st.end() + }) + + t.test('CP -> A1.1 -> Commit -> Flush() (-> A1.1)', async (st) => { + const sm = new DefaultStateManager() + + await sm.checkpoint() + await sm.putAccount(address, account) + await sm.commit() + await sm.flush() + st.equal((await sm.getAccount(address))!.nonce, 1n) + + sm.clearCaches() + st.equal((await sm.getAccount(address))!.nonce, 1n) + + st.end() + }) + + t.test('CP -> A1.1 -> Revert -> Flush() (-> Undefined)', async (st) => { + const sm = new DefaultStateManager() + + await sm.checkpoint() + await sm.putAccount(address, account) + await sm.revert() + await sm.flush() + st.equal(await sm.getAccount(address), undefined) + + sm.clearCaches() + st.equal(await sm.getAccount(address), undefined) + + st.end() + }) + + t.test('A1.1 -> CP -> Commit -> Flush() (-> A1.1)', async (st) => { + const sm = new DefaultStateManager() + + await sm.putAccount(address, account) + await sm.checkpoint() + await sm.commit() + await sm.flush() + st.equal((await sm.getAccount(address))!.nonce, 1n) + + sm.clearCaches() + st.equal((await sm.getAccount(address))!.nonce, 1n) + + st.end() + }) + + t.test('A1.1 -> CP -> Revert -> Flush() (-> A1.1)', async (st) => { + const sm = new DefaultStateManager() + + await sm.putAccount(address, account) + await sm.checkpoint() + await sm.revert() + await sm.flush() + st.equal((await sm.getAccount(address))!.nonce, 1n) + + sm.clearCaches() + st.equal((await sm.getAccount(address))!.nonce, 1n) + + st.end() + }) + + t.test('A1.1 -> CP -> A1.2 -> Commit -> Flush() (-> A1.2)', async (st) => { + const sm = new DefaultStateManager() + + await sm.putAccount(address, account) + await sm.checkpoint() + await sm.putAccount(address, account2) + await sm.commit() + await sm.flush() + st.equal((await sm.getAccount(address))!.nonce, 2n) + + sm.clearCaches() + st.equal((await sm.getAccount(address))!.nonce, 2n) + + st.end() + }) + + t.test('A1.1 -> CP -> A1.2 -> Commit -> A1.3 -> Flush() (-> A1.3)', async (st) => { + const sm = new DefaultStateManager() + + await sm.putAccount(address, account) + await sm.checkpoint() + await sm.putAccount(address, account2) + await sm.commit() + await sm.putAccount(address, account3) + await sm.flush() + st.equal((await sm.getAccount(address))!.nonce, 3n) + + sm.clearCaches() + st.equal((await sm.getAccount(address))!.nonce, 3n) + + st.end() + }) + + t.test('A1.1 -> CP -> A1.2 -> A1.3 -> Commit -> Flush() (-> A1.3)', async (st) => { + const sm = new DefaultStateManager() + + await sm.putAccount(address, account) + await sm.checkpoint() + await sm.putAccount(address, account2) + await sm.putAccount(address, account3) + await sm.commit() + await sm.flush() + st.equal((await sm.getAccount(address))!.nonce, 3n) + + sm.clearCaches() + st.equal((await sm.getAccount(address))!.nonce, 3n) + + st.end() + }) + + t.test('CP -> A1.1 -> A1.2 -> Commit -> Flush() (-> A1.2)', async (st) => { + const sm = new DefaultStateManager() + + await sm.checkpoint() + await sm.putAccount(address, account) + await sm.putAccount(address, account2) + await sm.commit() + await sm.flush() + st.equal((await sm.getAccount(address))!.nonce, 2n) + + sm.clearCaches() + st.equal((await sm.getAccount(address))!.nonce, 2n) + + st.end() + }) + + t.test('CP -> A1.1 -> A1.2 -> Revert -> Flush() (-> Undefined)', async (st) => { + const sm = new DefaultStateManager() + + await sm.checkpoint() + await sm.putAccount(address, account) + + await sm.putAccount(address, account2) + await sm.revert() + await sm.flush() + st.equal(await sm.getAccount(address), undefined) + + sm.clearCaches() + st.equal(await sm.getAccount(address), undefined) + + st.end() + }) + + t.test('A1.1 -> CP -> A1.2 -> Revert -> Flush() (-> A1.1)', async (st) => { + const sm = new DefaultStateManager() + + await sm.putAccount(address, account) + await sm.checkpoint() + await sm.putAccount(address, account2) + await sm.revert() + await sm.flush() + st.equal((await sm.getAccount(address))!.nonce, 1n) + + sm.clearCaches() + st.equal((await sm.getAccount(address))!.nonce, 1n) + + st.end() + }) + + t.test( + 'A1.1 -> CP -> A1.2 -> CP -> A1.3 -> Commit -> Commit -> Flush() (-> A1.3)', + async (st) => { + const sm = new DefaultStateManager() + + await sm.putAccount(address, account) + await sm.checkpoint() + await sm.putAccount(address, account2) + await sm.checkpoint() + await sm.putAccount(address, account3) + await sm.commit() + await sm.commit() + await sm.flush() + st.equal((await sm.getAccount(address))!.nonce, 3n) + + sm.clearCaches() + st.equal((await sm.getAccount(address))!.nonce, 3n) + + st.end() + } + ) + + t.test( + 'A1.1 -> CP -> A1.2 -> CP -> A1.3 -> Commit -> Revert -> Flush() (-> A1.1)', + async (st) => { + const sm = new DefaultStateManager() + + await sm.putAccount(address, account) + await sm.checkpoint() + await sm.putAccount(address, account2) + await sm.checkpoint() + await sm.putAccount(address, account3) + await sm.commit() + await sm.revert() + await sm.flush() + st.equal((await sm.getAccount(address))!.nonce, 1n) + + sm.clearCaches() + st.equal((await sm.getAccount(address))!.nonce, 1n) + + st.end() + } + ) + + t.test( + 'A1.1 -> CP -> A1.2 -> CP -> A1.3 -> Revert -> Commit -> Flush() (-> A1.2)', + async (st) => { + const sm = new DefaultStateManager() + + await sm.putAccount(address, account) + await sm.checkpoint() + await sm.putAccount(address, account2) + await sm.checkpoint() + await sm.putAccount(address, account3) + await sm.revert() + await sm.commit() + await sm.flush() + st.equal((await sm.getAccount(address))!.nonce, 2n) + + sm.clearCaches() + st.equal((await sm.getAccount(address))!.nonce, 2n) + + st.end() + } + ) + + t.test( + 'A1.1 -> CP -> A1.2 -> CP -> A1.3 -> Revert -> A1.4 -> Commit -> Flush() (-> A1.4)', + async (st) => { + const sm = new DefaultStateManager() + + await sm.putAccount(address, account) + await sm.checkpoint() + await sm.putAccount(address, account2) + await sm.checkpoint() + await sm.putAccount(address, account3) + await sm.revert() + await sm.putAccount(address, account4) + await sm.commit() + await sm.flush() + st.equal((await sm.getAccount(address))!.nonce, 4n) + + sm.clearCaches() + st.equal((await sm.getAccount(address))!.nonce, 4n) + + st.end() + } + ) + + t.test( + 'A1.1 -> CP -> A1.2 -> CP -> A1.3 -> Revert -> A1.4 -> CP -> A1.5 -> Commit -> Commit -> Flush() (-> A1.5)', + async (st) => { + const sm = new DefaultStateManager() + + await sm.putAccount(address, account) + await sm.checkpoint() + await sm.putAccount(address, account2) + await sm.checkpoint() + await sm.putAccount(address, account3) + await sm.revert() + await sm.putAccount(address, account4) + await sm.checkpoint() + await sm.putAccount(address, account5) + await sm.commit() + await sm.commit() + await sm.flush() + st.equal((await sm.getAccount(address))!.nonce, 5n) + + sm.clearCaches() + st.equal((await sm.getAccount(address))!.nonce, 5n) + + st.end() + } + ) +}) diff --git a/packages/statemanager/test/checkpointing.storage.spec.ts b/packages/statemanager/test/checkpointing.storage.spec.ts new file mode 100644 index 0000000000..8f1134b455 --- /dev/null +++ b/packages/statemanager/test/checkpointing.storage.spec.ts @@ -0,0 +1,319 @@ +import { Account, Address, hexStringToBytes } from '@ethereumjs/util' +import * as tape from 'tape' + +import { DefaultStateManager } from '../src' + +tape('StateManager -> Storage Checkpointing', (t) => { + const address = new Address(hexStringToBytes('11'.repeat(20))) + const account = new Account() + const key = hexStringToBytes('01'.repeat(32)) + const value = hexStringToBytes('01') + const value2 = hexStringToBytes('02') + const value3 = hexStringToBytes('03') + const value4 = hexStringToBytes('04') + const value5 = hexStringToBytes('05') + + t.test('No CP -> S1 -> Flush() (-> S1)', async (st) => { + const sm = new DefaultStateManager() + await sm.putAccount(address, account) + + await sm.putContractStorage(address, key, value) + await sm.flush() + st.deepEqual(await sm.getContractStorage(address, key), value) + + sm.clearCaches() + st.deepEqual(await sm.getContractStorage(address, key), value) + + st.end() + }) + + t.test('CP -> S1.1 -> Commit -> Flush() (-> S1.1)', async (st) => { + const sm = new DefaultStateManager() + await sm.putAccount(address, account) + + await sm.checkpoint() + await sm.putContractStorage(address, key, value) + await sm.commit() + await sm.flush() + st.deepEqual(await sm.getContractStorage(address, key), value) + + sm.clearCaches() + st.deepEqual(await sm.getContractStorage(address, key), value) + + st.end() + }) + + t.test('CP -> S1.1 -> Revert -> Flush() (-> Undefined)', async (st) => { + const sm = new DefaultStateManager() + await sm.putAccount(address, account) + + await sm.checkpoint() + await sm.putContractStorage(address, key, value) + await sm.revert() + await sm.flush() + st.deepEqual(await sm.getContractStorage(address, key), new Uint8Array(0)) + + sm.clearCaches() + + st.deepEqual(await sm.getContractStorage(address, key), new Uint8Array(0)) + + st.end() + }) + + t.test('S1.1 -> CP -> Commit -> Flush() (-> S1.1)', async (st) => { + const sm = new DefaultStateManager() + await sm.putAccount(address, account) + + await sm.putContractStorage(address, key, value) + await sm.checkpoint() + await sm.commit() + await sm.flush() + st.deepEqual(await sm.getContractStorage(address, key), value) + + sm.clearCaches() + st.deepEqual(await sm.getContractStorage(address, key), value) + + st.end() + }) + + t.test('S1.1 -> CP -> Revert -> Flush() (-> S1.1)', async (st) => { + const sm = new DefaultStateManager() + await sm.putAccount(address, account) + + await sm.putContractStorage(address, key, value) + await sm.checkpoint() + await sm.revert() + await sm.flush() + st.deepEqual(await sm.getContractStorage(address, key), value) + + sm.clearCaches() + st.deepEqual(await sm.getContractStorage(address, key), value) + + st.end() + }) + + t.test('S1.1 -> CP -> S1.2 -> Commit -> Flush() (-> S1.2)', async (st) => { + const sm = new DefaultStateManager() + await sm.putAccount(address, account) + + await sm.putContractStorage(address, key, value) + await sm.checkpoint() + await sm.putContractStorage(address, key, value2) + await sm.commit() + await sm.flush() + st.deepEqual(await sm.getContractStorage(address, key), value2) + + sm.clearCaches() + st.deepEqual(await sm.getContractStorage(address, key), value2) + + st.end() + }) + + t.test('S1.1 -> CP -> S1.2 -> Commit -> S1.3 -> Flush() (-> S1.3)', async (st) => { + const sm = new DefaultStateManager() + await sm.putAccount(address, account) + + await sm.putContractStorage(address, key, value) + await sm.checkpoint() + await sm.putContractStorage(address, key, value2) + await sm.commit() + await sm.putContractStorage(address, key, value3) + await sm.flush() + st.deepEqual(await sm.getContractStorage(address, key), value3) + + sm.clearCaches() + st.deepEqual(await sm.getContractStorage(address, key), value3) + + st.end() + }) + + t.test('S1.1 -> CP -> S1.2 -> S1.3 -> Commit -> Flush() (-> S1.3)', async (st) => { + const sm = new DefaultStateManager() + await sm.putAccount(address, account) + + await sm.putContractStorage(address, key, value) + await sm.checkpoint() + await sm.putContractStorage(address, key, value2) + await sm.putContractStorage(address, key, value3) + await sm.commit() + await sm.flush() + st.deepEqual(await sm.getContractStorage(address, key), value3) + + sm.clearCaches() + st.deepEqual(await sm.getContractStorage(address, key), value3) + + st.end() + }) + + t.test('CP -> S1.1 -> S1.2 -> Commit -> Flush() (-> S1.2)', async (st) => { + const sm = new DefaultStateManager() + await sm.putAccount(address, account) + + await sm.checkpoint() + await sm.putContractStorage(address, key, value) + await sm.putContractStorage(address, key, value2) + await sm.commit() + await sm.flush() + st.deepEqual((await sm.getContractStorage(address, key))!, value2) + + sm.clearCaches() + st.deepEqual((await sm.getContractStorage(address, key))!, value2) + + st.end() + }) + + t.test('CP -> S1.1 -> S1.2 -> Revert -> Flush() (-> Undefined)', async (st) => { + const sm = new DefaultStateManager() + await sm.putAccount(address, account) + + await sm.checkpoint() + await sm.putContractStorage(address, key, value) + + await sm.putContractStorage(address, key, value2) + await sm.revert() + await sm.flush() + st.deepEqual(await sm.getContractStorage(address, key), new Uint8Array(0)) + + sm.clearCaches() + st.deepEqual(await sm.getContractStorage(address, key), new Uint8Array(0)) + + st.end() + }) + + t.test('S1.1 -> CP -> S1.2 -> Revert -> Flush() (-> S1.1)', async (st) => { + const sm = new DefaultStateManager() + await sm.putAccount(address, account) + + await sm.putContractStorage(address, key, value) + await sm.checkpoint() + await sm.putContractStorage(address, key, value2) + await sm.revert() + await sm.flush() + st.deepEqual(await sm.getContractStorage(address, key), value) + + sm.clearCaches() + st.deepEqual(await sm.getContractStorage(address, key), value) + + st.end() + }) + + t.test( + 'S1.1 -> CP -> S1.2 -> CP -> S1.3 -> Commit -> Commit -> Flush() (-> S1.3)', + async (st) => { + const sm = new DefaultStateManager() + await sm.putAccount(address, account) + + await sm.putContractStorage(address, key, value) + await sm.checkpoint() + await sm.putContractStorage(address, key, value2) + await sm.checkpoint() + await sm.putContractStorage(address, key, value3) + await sm.commit() + await sm.commit() + await sm.flush() + st.deepEqual(await sm.getContractStorage(address, key), value3) + + sm.clearCaches() + st.deepEqual(await sm.getContractStorage(address, key), value3) + + st.end() + } + ) + + t.test( + 'S1.1 -> CP -> S1.2 -> CP -> S1.3 -> Commit -> Revert -> Flush() (-> S1.1)', + async (st) => { + const sm = new DefaultStateManager() + await sm.putAccount(address, account) + + await sm.putContractStorage(address, key, value) + await sm.checkpoint() + await sm.putContractStorage(address, key, value2) + await sm.checkpoint() + await sm.putContractStorage(address, key, value3) + await sm.commit() + await sm.revert() + await sm.flush() + st.deepEqual(await sm.getContractStorage(address, key), value) + + sm.clearCaches() + st.deepEqual(await sm.getContractStorage(address, key), value) + + st.end() + } + ) + + t.test( + 'S1.1 -> CP -> S1.2 -> CP -> S1.3 -> Revert -> Commit -> Flush() (-> S1.2)', + async (st) => { + const sm = new DefaultStateManager() + await sm.putAccount(address, account) + + await sm.putContractStorage(address, key, value) + await sm.checkpoint() + await sm.putContractStorage(address, key, value2) + await sm.checkpoint() + await sm.putContractStorage(address, key, value3) + await sm.revert() + await sm.commit() + await sm.flush() + st.deepEqual(await sm.getContractStorage(address, key), value2) + + sm.clearCaches() + st.deepEqual(await sm.getContractStorage(address, key), value2) + + st.end() + } + ) + + t.test( + 'S1.1 -> CP -> S1.2 -> CP -> S1.3 -> Revert -> S1.4 -> Commit -> Flush() (-> S1.4)', + async (st) => { + const sm = new DefaultStateManager() + await sm.putAccount(address, account) + + await sm.putContractStorage(address, key, value) + await sm.checkpoint() + await sm.putContractStorage(address, key, value2) + await sm.checkpoint() + await sm.putContractStorage(address, key, value3) + await sm.revert() + await sm.putContractStorage(address, key, value4) + await sm.commit() + await sm.flush() + st.deepEqual(await sm.getContractStorage(address, key), value4) + + sm.clearCaches() + st.deepEqual(await sm.getContractStorage(address, key), value4) + + st.end() + } + ) + + t.test( + 'S1.1 -> CP -> S1.2 -> CP -> S1.3 -> Revert -> S1.4 -> CP -> S1.5 -> Commit -> Commit -> Flush() (-> S1.5)', + async (st) => { + const sm = new DefaultStateManager() + await sm.putAccount(address, account) + + await sm.putContractStorage(address, key, value) + await sm.checkpoint() + await sm.putContractStorage(address, key, value2) + await sm.checkpoint() + await sm.putContractStorage(address, key, value3) + await sm.revert() + await sm.putContractStorage(address, key, value4) + await sm.checkpoint() + await sm.putContractStorage(address, key, value5) + await sm.commit() + await sm.commit() + await sm.flush() + st.deepEqual(await sm.getContractStorage(address, key), value5) + + sm.clearCaches() + st.deepEqual(await sm.getContractStorage(address, key), value5) + + st.end() + } + ) +}) diff --git a/packages/statemanager/test/ethersStateManager.spec.ts b/packages/statemanager/test/ethersStateManager.spec.ts index 45ab64a462..4ce94c59a1 100644 --- a/packages/statemanager/test/ethersStateManager.spec.ts +++ b/packages/statemanager/test/ethersStateManager.spec.ts @@ -2,6 +2,7 @@ import { Block } from '@ethereumjs/block' import { Chain, Common, Hardfork } from '@ethereumjs/common' import { FeeMarketEIP1559Transaction, TransactionFactory } from '@ethereumjs/tx' import { + Account, Address, bigIntToBytes, equalsBytes, @@ -58,11 +59,13 @@ tape('Ethers State Manager API tests', async (t) => { const state = new EthersStateManager({ provider, blockTag: 1n }) const vitalikDotEth = Address.fromString('0xd8da6bf26964af9d7eed9e03e53415d37aa96045') const account = await state.getAccount(vitalikDotEth) - t.ok(account.nonce > 0n, 'Vitalik.eth returned a valid nonce') + t.ok(account!.nonce > 0n, 'Vitalik.eth returned a valid nonce') - await state.putAccount(vitalikDotEth, account) + await state.putAccount(vitalikDotEth, account!) - const retrievedVitalikAccount = (state as any)._cache.get(vitalikDotEth) + const retrievedVitalikAccount = Account.fromRlpSerializedAccount( + (state as any)._accountCache.get(vitalikDotEth)!.accountRLP + ) t.ok(retrievedVitalikAccount.nonce > 0n, 'Vitalik.eth is stored in cache') const doesThisAccountExist = await state.accountExists( diff --git a/packages/statemanager/test/proofStateManager.spec.ts b/packages/statemanager/test/proofStateManager.spec.ts index 51ddc44ba2..a0368187c8 100644 --- a/packages/statemanager/test/proofStateManager.spec.ts +++ b/packages/statemanager/test/proofStateManager.spec.ts @@ -1,5 +1,12 @@ import { Trie } from '@ethereumjs/trie' -import { Address, bytesToHex, hexStringToBytes, zeros } from '@ethereumjs/util' +import { + Account, + Address, + bytesToHex, + hexStringToBytes, + randomBytes, + zeros, +} from '@ethereumjs/util' import { keccak256 } from 'ethereum-cryptography/keccak' import * as tape from 'tape' @@ -17,21 +24,28 @@ tape('ProofStateManager', (t) => { const code = hexStringToBytes('6000') const stateManager = new DefaultStateManager() await stateManager.checkpoint() + await stateManager.putAccount(address, new Account()) await stateManager.putContractStorage(address, key, value) await stateManager.putContractCode(address, code) const account = await stateManager.getAccount(address) - account.balance = BigInt(1) - account.nonce = BigInt(2) - await stateManager.putAccount(address, account) + account!.balance = BigInt(1) + account!.nonce = BigInt(2) + await stateManager.putAccount(address, account!) const address2 = new Address(hexStringToBytes('20'.repeat(20))) const account2 = await stateManager.getAccount(address2) - account.nonce = BigInt(2) - await stateManager.putAccount(address2, account2) + account!.nonce = BigInt(2) + await stateManager.putAccount(address2, account2!) await stateManager.commit() await stateManager.flush() const proof = await stateManager.getProof(address, [key]) st.ok(await stateManager.verifyProof(proof)) + const nonExistenceProof = await stateManager.getProof(Address.fromPrivateKey(randomBytes(32))) + st.equals( + await stateManager.verifyProof(nonExistenceProof), + true, + 'verified proof of non-existence of account' + ) st.end() }) @@ -41,7 +55,7 @@ tape('ProofStateManager', (t) => { // Account: 0xc626553e7c821d0f8308c28d56c60e3c15f8d55a // Storage slots: empty list const address = Address.fromString('0xc626553e7c821d0f8308c28d56c60e3c15f8d55a') - const trie = new Trie({ useKeyHashing: true }) + const trie = await Trie.create({ useKeyHashing: true }) const stateManager = new DefaultStateManager({ trie }) // Dump all the account proof data in the DB let stateRoot: Uint8Array | undefined @@ -83,6 +97,7 @@ tape('ProofStateManager', (t) => { await trie._db.put(key, bufferData) } trie.root(stateRoot!) + await stateManager.putAccount(address, new Account()) const proof = await stateManager.getProof(address) st.deepEqual(ropsten_nonexistentAccount, proof) st.ok(await stateManager.verifyProof(ropsten_nonexistentAccount)) diff --git a/packages/statemanager/test/stateManager.account.spec.ts b/packages/statemanager/test/stateManager.account.spec.ts new file mode 100644 index 0000000000..9d0b98aa26 --- /dev/null +++ b/packages/statemanager/test/stateManager.account.spec.ts @@ -0,0 +1,177 @@ +import { Address, KECCAK256_RLP, bytesToHex, equalsBytes, hexStringToBytes } from '@ethereumjs/util' +import * as tape from 'tape' +// explicitly import `inherits` to fix karma-typescript issue +// eslint-disable-next-line @typescript-eslint/no-unused-vars +import { inherits } from 'util' + +import { DefaultStateManager } from '../src' + +import { createAccount } from './util' + +tape('StateManager -> General/Account', (t) => { + for (const accountCacheOpts of [{ deactivate: false }, { deactivate: true }]) { + t.test('should instantiate', async (st) => { + const stateManager = new DefaultStateManager({ accountCacheOpts }) + + st.deepEqual(stateManager._trie.root(), KECCAK256_RLP, 'it has default root') + const res = await stateManager.getStateRoot() + st.deepEqual(res, KECCAK256_RLP, 'it has default root') + st.end() + }) + + t.test('should set the state root to empty', async (st) => { + const stateManager = new DefaultStateManager({ accountCacheOpts }) + st.ok(equalsBytes(stateManager._trie.root(), KECCAK256_RLP), 'it has default root') + + // commit some data to the trie + const address = new Address(hexStringToBytes('a94f5374fce5edbc8e2a8697c15331677e6ebf0b')) + const account = createAccount(BigInt(0), BigInt(1000)) + await stateManager.checkpoint() + await stateManager.putAccount(address, account) + await stateManager.commit() + await stateManager.flush() + st.ok(!equalsBytes(stateManager._trie.root(), KECCAK256_RLP), 'it has a new root') + + // set state root to empty trie root + await stateManager.setStateRoot(KECCAK256_RLP) + + const res = await stateManager.getStateRoot() + st.ok(equalsBytes(res, KECCAK256_RLP), 'it has default root') + st.end() + }) + + t.test('should clear the cache when the state root is set', async (st) => { + const stateManager = new DefaultStateManager({ accountCacheOpts }) + const address = new Address(hexStringToBytes('a94f5374fce5edbc8e2a8697c15331677e6ebf0b')) + const account = createAccount() + + // test account storage cache + const initialStateRoot = await stateManager.getStateRoot() + await stateManager.checkpoint() + await stateManager.putAccount(address, account) + + const account0 = await stateManager.getAccount(address) + st.equal(account0!.balance, account.balance, 'account value is set in the cache') + + await stateManager.commit() + const account1 = await stateManager.getAccount(address) + st.equal(account1!.balance, account.balance, 'account value is set in the state trie') + + await stateManager.setStateRoot(initialStateRoot) + const account2 = await stateManager.getAccount(address) + st.equal(account2, undefined, 'account is not present any more in original state root') + + // test contract storage cache + await stateManager.checkpoint() + const key = hexStringToBytes( + '1234567890123456789012345678901234567890123456789012345678901234' + ) + const value = hexStringToBytes('1234') + await stateManager.putAccount(address, account) + await stateManager.putContractStorage(address, key, value) + + const contract0 = await stateManager.getContractStorage(address, key) + st.ok(equalsBytes(contract0, value), "contract key's value is set in the _storageTries cache") + + await stateManager.commit() + await stateManager.setStateRoot(initialStateRoot) + try { + await stateManager.getContractStorage(address, key) + } catch (e) { + st.pass('should throw if getContractStorage() is called on non existing address') + } + + st.end() + }) + + t.test( + 'should put and get account, and add to the underlying cache if the account is not found', + async (st) => { + const stateManager = new DefaultStateManager({ accountCacheOpts }) + const account = createAccount() + const address = new Address(hexStringToBytes('a94f5374fce5edbc8e2a8697c15331677e6ebf0b')) + + await stateManager.putAccount(address, account) + + const res1 = await stateManager.getAccount(address) + + st.equal(res1!.balance, BigInt(0xfff384)) + + await stateManager.flush() + stateManager._accountCache?.clear() + + const res2 = await stateManager.getAccount(address) + + st.ok(equalsBytes(res1!.serialize(), res2!.serialize())) + + st.end() + } + ) + + t.test('should return false for a non-existent account', async (st) => { + const stateManager = new DefaultStateManager({ accountCacheOpts }) + const address = new Address(hexStringToBytes('a94f5374fce5edbc8e2a8697c15331677e6ebf0b')) + + const res = await stateManager.accountExists(address) + + st.notOk(res) + + st.end() + }) + + t.test('should return true for an existent account', async (st) => { + const stateManager = new DefaultStateManager({ accountCacheOpts }) + const account = createAccount(BigInt(0x1), BigInt(0x1)) + const address = new Address(hexStringToBytes('a94f5374fce5edbc8e2a8697c15331677e6ebf0b')) + + await stateManager.putAccount(address, account) + + const res = await stateManager.accountExists(address) + + st.ok(res) + + st.end() + }) + + t.test('should modify account fields correctly', async (st) => { + const stateManager = new DefaultStateManager({ accountCacheOpts }) + const account = createAccount() + const address = new Address(hexStringToBytes('a94f5374fce5edbc8e2a8697c15331677e6ebf0b')) + await stateManager.putAccount(address, account) + + await stateManager.modifyAccountFields(address, { balance: BigInt(1234) }) + + const res1 = await stateManager.getAccount(address) + + st.equal(res1!.balance, BigInt(0x4d2)) + + await stateManager.modifyAccountFields(address, { nonce: BigInt(1) }) + + const res2 = await stateManager.getAccount(address) + + st.equal(res2!.nonce, BigInt(1)) + + await stateManager.modifyAccountFields(address, { + codeHash: hexStringToBytes( + 'd748bf26ab37599c944babfdbeecf6690801bd61bf2670efb0a34adfc6dca10b' + ), + storageRoot: hexStringToBytes( + 'cafd881ab193703b83816c49ff6c2bf6ba6f464a1be560c42106128c8dbc35e7' + ), + }) + + const res3 = await stateManager.getAccount(address) + + st.equal( + bytesToHex(res3!.codeHash), + 'd748bf26ab37599c944babfdbeecf6690801bd61bf2670efb0a34adfc6dca10b' + ) + st.equal( + bytesToHex(res3!.storageRoot), + 'cafd881ab193703b83816c49ff6c2bf6ba6f464a1be560c42106128c8dbc35e7' + ) + + st.end() + }) + } +}) diff --git a/packages/statemanager/test/stateManager.code.spec.ts b/packages/statemanager/test/stateManager.code.spec.ts new file mode 100644 index 0000000000..6224b5d433 --- /dev/null +++ b/packages/statemanager/test/stateManager.code.spec.ts @@ -0,0 +1,157 @@ +import { Account, Address, equalsBytes, hexStringToBytes } from '@ethereumjs/util' +import * as tape from 'tape' +// explicitly import `inherits` to fix karma-typescript issue +// eslint-disable-next-line @typescript-eslint/no-unused-vars +import { inherits } from 'util' + +import { DefaultStateManager } from '../src' + +import { createAccount } from './util' + +tape('StateManager -> Code', (t) => { + for (const accountCacheOpts of [{ deactivate: false }, { deactivate: true }]) { + t.test('should store codehashes using a prefix', async (st) => { + /* + This test is mostly an example of why a code prefix is necessary + I an address, we put two storage values. The preimage of the (storage trie) root hash is known + This preimage is used as codeHash + + NOTE: Currently, the only problem which this code prefix fixes, is putting 0x80 as contract code + -> This hashes to the empty trie node hash (0x80 = RLP([])), so keccak256(0x80) = empty trie node hash + -> Therefore, each empty state trie now points to 0x80, which is not a valid trie node, which crashes @ethereumjs/trie + */ + + // Setup + const stateManager = new DefaultStateManager({ accountCacheOpts }) + const codeStateManager = new DefaultStateManager({ accountCacheOpts }) + const address1 = new Address(hexStringToBytes('a94f5374fce5edbc8e2a8697c15331677e6ebf0b')) + const account = createAccount() + const key1 = hexStringToBytes('00'.repeat(32)) + const key2 = hexStringToBytes('00'.repeat(31) + '01') + + await stateManager.putAccount(address1, account) + await stateManager.putContractStorage(address1, key1, key2) + await stateManager.putContractStorage(address1, key2, key2) + const root = await stateManager.getStateRoot() + // @ts-expect-error + const rawNode = await stateManager._trie._db.get(root) + + await codeStateManager.putContractCode(address1, rawNode!) + + let codeSlot1 = await codeStateManager.getContractStorage(address1, key1) + let codeSlot2 = await codeStateManager.getContractStorage(address1, key2) + + st.ok(codeSlot1.length === 0, 'slot 0 is empty') + st.ok(codeSlot2.length === 0, 'slot 1 is empty') + + const code = await codeStateManager.getContractCode(address1) + st.ok(code.length > 0, 'code deposited correctly') + + const slot1 = await stateManager.getContractStorage(address1, key1) + const slot2 = await stateManager.getContractStorage(address1, key2) + + st.ok(slot1.length > 0, 'storage key0 deposited correctly') + st.ok(slot2.length > 0, 'storage key1 deposited correctly') + + let slotCode = await stateManager.getContractCode(address1) + st.ok(slotCode.length === 0, 'code cannot be loaded') + + // Checks by either setting state root to codeHash, or codeHash to stateRoot + // The knowledge of the tries should not change + let account1 = await stateManager.getAccount(address1) + account1!.codeHash = root + + await stateManager.putAccount(address1, account1!) + + slotCode = await stateManager.getContractCode(address1) + st.ok(slotCode.length === 0, 'code cannot be loaded') // This test fails if no code prefix is used + + account1 = await codeStateManager.getAccount(address1) + account1!.storageRoot = root + + await codeStateManager.putAccount(address1, account1!) + + codeSlot1 = await codeStateManager.getContractStorage(address1, key1) + codeSlot2 = await codeStateManager.getContractStorage(address1, key2) + + st.ok(codeSlot1.length === 0, 'slot 0 is empty') + st.ok(codeSlot2.length === 0, 'slot 1 is empty') + + st.end() + }) + + t.test('should set and get code', async (st) => { + const stateManager = new DefaultStateManager({ accountCacheOpts }) + const address = new Address(hexStringToBytes('a94f5374fce5edbc8e2a8697c15331677e6ebf0b')) + const code = hexStringToBytes( + '73095e7baea6a6c7c4c2dfeb977efac326af552d873173095e7baea6a6c7c4c2dfeb977efac326af552d873157' + ) + const raw = { + nonce: '0x0', + balance: '0x03e7', + stateRoot: '0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421', + codeHash: '0xb30fb32201fe0486606ad451e1a61e2ae1748343cd3d411ed992ffcc0774edd4', + } + const account = Account.fromAccountData(raw) + await stateManager.putAccount(address, account) + await stateManager.putContractCode(address, code) + const codeRetrieved = await stateManager.getContractCode(address) + st.ok(equalsBytes(code, codeRetrieved)) + st.end() + }) + + t.test('should not get code if is not contract', async (st) => { + const stateManager = new DefaultStateManager({ accountCacheOpts }) + const address = new Address(hexStringToBytes('a94f5374fce5edbc8e2a8697c15331677e6ebf0b')) + const raw = { + nonce: '0x0', + balance: '0x03e7', + } + const account = Account.fromAccountData(raw) + await stateManager.putAccount(address, account) + const code = await stateManager.getContractCode(address) + st.ok(equalsBytes(code, new Uint8Array(0))) + st.end() + }) + + t.test('should set empty code', async (st) => { + const stateManager = new DefaultStateManager({ accountCacheOpts }) + const address = new Address(hexStringToBytes('a94f5374fce5edbc8e2a8697c15331677e6ebf0b')) + const raw = { + nonce: '0x0', + balance: '0x03e7', + } + const account = Account.fromAccountData(raw) + const code = new Uint8Array(0) + await stateManager.putAccount(address, account) + await stateManager.putContractCode(address, code) + const codeRetrieved = await stateManager.getContractCode(address) + st.ok(equalsBytes(codeRetrieved, new Uint8Array(0))) + st.end() + }) + + t.test('should prefix codehashes by default', async (st) => { + const stateManager = new DefaultStateManager({ accountCacheOpts }) + const address = new Address(hexStringToBytes('a94f5374fce5edbc8e2a8697c15331677e6ebf0b')) + const code = hexStringToBytes('80') + await stateManager.putContractCode(address, code) + const codeRetrieved = await stateManager.getContractCode(address) + st.ok(equalsBytes(codeRetrieved, code)) + st.end() + }) + + t.test('should not prefix codehashes if prefixCodeHashes = false', async (st) => { + const stateManager = new DefaultStateManager({ + prefixCodeHashes: false, + }) + const address = new Address(hexStringToBytes('a94f5374fce5edbc8e2a8697c15331677e6ebf0b')) + const code = hexStringToBytes('80') + try { + await stateManager.putContractCode(address, code) + st.fail('should throw') + } catch (e) { + st.pass('successfully threw') + } + }) + } +}) diff --git a/packages/statemanager/test/stateManager.spec.ts b/packages/statemanager/test/stateManager.spec.ts deleted file mode 100644 index 23480495dd..0000000000 --- a/packages/statemanager/test/stateManager.spec.ts +++ /dev/null @@ -1,520 +0,0 @@ -import { - Account, - Address, - KECCAK256_RLP, - KECCAK256_RLP_S, - hexStringToBytes, - unpadBytes, - zeros, -} from '@ethereumjs/util' -import { keccak256 } from 'ethereum-cryptography/keccak' -import { bytesToHex, concatBytes, equalsBytes, hexToBytes } from 'ethereum-cryptography/utils' -import * as tape from 'tape' -// explicitly import `inherits` to fix karma-typescript issue -// eslint-disable-next-line @typescript-eslint/no-unused-vars -import { inherits } from 'util' - -import { DefaultStateManager } from '../src' - -import { createAccount } from './util' - -tape('StateManager', (t) => { - t.test('should instantiate', async (st) => { - const stateManager = new DefaultStateManager() - - st.deepEqual(stateManager._trie.root(), KECCAK256_RLP, 'it has default root') - const res = await stateManager.getStateRoot() - st.deepEqual(res, KECCAK256_RLP, 'it has default root') - st.end() - }) - - t.test('should set the state root to empty', async (st) => { - const stateManager = new DefaultStateManager() - st.ok(equalsBytes(stateManager._trie.root(), KECCAK256_RLP), 'it has default root') - - // commit some data to the trie - const address = new Address(hexStringToBytes('a94f5374fce5edbc8e2a8697c15331677e6ebf0b')) - const account = createAccount(BigInt(0), BigInt(1000)) - await stateManager.checkpoint() - await stateManager.putAccount(address, account) - await stateManager.commit() - await stateManager.flush() - st.ok(!equalsBytes(stateManager._trie.root(), KECCAK256_RLP), 'it has a new root') - - // set state root to empty trie root - const emptyTrieRoot = hexToBytes(KECCAK256_RLP_S) - await stateManager.setStateRoot(emptyTrieRoot) - - const res = await stateManager.getStateRoot() - st.ok(equalsBytes(res, KECCAK256_RLP), 'it has default root') - st.end() - }) - - t.test('should clear the cache when the state root is set', async (st) => { - const stateManager = new DefaultStateManager() - const address = new Address(hexStringToBytes('a94f5374fce5edbc8e2a8697c15331677e6ebf0b')) - const account = createAccount() - - // test account storage cache - const initialStateRoot = await stateManager.getStateRoot() - await stateManager.checkpoint() - await stateManager.putAccount(address, account) - - const account0 = await stateManager.getAccount(address) - st.equal(account0.balance, account.balance, 'account value is set in the cache') - - await stateManager.commit() - const account1 = await stateManager.getAccount(address) - st.equal(account1.balance, account.balance, 'account value is set in the state trie') - - await stateManager.setStateRoot(initialStateRoot) - const account2 = await stateManager.getAccount(address) - st.equal(account2.balance, BigInt(0), 'account value is set to 0 in original state root') - - // test contract storage cache - await stateManager.checkpoint() - const key = hexStringToBytes( - '0x1234567890123456789012345678901234567890123456789012345678901234' - ) - const value = hexStringToBytes('0x1234') - await stateManager.putContractStorage(address, key, value) - - const contract0 = await stateManager.getContractStorage(address, key) - st.ok(equalsBytes(contract0, value), "contract key's value is set in the _storageTries cache") - - await stateManager.commit() - await stateManager.setStateRoot(initialStateRoot) - const contract1 = await stateManager.getContractStorage(address, key) - st.equal(contract1.length, 0, "contract key's value is unset in the _storageTries cache") - - st.end() - }) - - t.test( - 'should put and get account, and add to the underlying cache if the account is not found', - async (st) => { - const stateManager = new DefaultStateManager() - const account = createAccount() - const address = new Address(hexStringToBytes('a94f5374fce5edbc8e2a8697c15331677e6ebf0b')) - - await stateManager.putAccount(address, account) - - const res1 = await stateManager.getAccount(address) - - st.equal(res1.balance, BigInt(0xfff384)) - - await stateManager._cache.flush() - stateManager._cache.clear() - - const res2 = await stateManager.getAccount(address) - - st.equal(stateManager._cache._cache.begin().pointer[0], bytesToHex(address.bytes)) - st.ok(equalsBytes(res1.serialize(), res2.serialize())) - - st.end() - } - ) - - t.test( - 'should call the callback with a boolean representing emptiness, when the account is empty', - async (st) => { - const stateManager = new DefaultStateManager() - const address = new Address(hexStringToBytes('a94f5374fce5edbc8e2a8697c15331677e6ebf0b')) - - const res = await stateManager.accountIsEmpty(address) - - st.ok(res) - - st.end() - } - ) - - t.test('should return false for a non-existent account', async (st) => { - const stateManager = new DefaultStateManager() - const address = new Address(hexStringToBytes('a94f5374fce5edbc8e2a8697c15331677e6ebf0b')) - - const res = await stateManager.accountExists(address) - - st.notOk(res) - - st.end() - }) - - t.test('should return true for an existent account', async (st) => { - const stateManager = new DefaultStateManager() - const account = createAccount(BigInt(0x1), BigInt(0x1)) - const address = new Address(hexStringToBytes('a94f5374fce5edbc8e2a8697c15331677e6ebf0b')) - - await stateManager.putAccount(address, account) - - const res = await stateManager.accountExists(address) - - st.ok(res) - - st.end() - }) - - t.test( - 'should call the callback with a false boolean representing non-emptiness when the account is not empty', - async (st) => { - const stateManager = new DefaultStateManager() - const account = createAccount(BigInt(0x1), BigInt(0x1)) - const address = new Address(hexStringToBytes('a94f5374fce5edbc8e2a8697c15331677e6ebf0b')) - - await stateManager.putAccount(address, account) - - const res = await stateManager.accountIsEmpty(address) - - st.notOk(res) - - st.end() - } - ) - - t.test('should modify account fields correctly', async (st) => { - const stateManager = new DefaultStateManager() - const account = createAccount() - const address = new Address(hexStringToBytes('a94f5374fce5edbc8e2a8697c15331677e6ebf0b')) - await stateManager.putAccount(address, account) - - await stateManager.modifyAccountFields(address, { balance: BigInt(1234) }) - - const res1 = await stateManager.getAccount(address) - - st.equal(res1.balance, BigInt(0x4d2)) - - await stateManager.modifyAccountFields(address, { nonce: BigInt(1) }) - - const res2 = await stateManager.getAccount(address) - - st.equal(res2.nonce, BigInt(1)) - - await stateManager.modifyAccountFields(address, { - codeHash: hexStringToBytes( - 'd748bf26ab37599c944babfdbeecf6690801bd61bf2670efb0a34adfc6dca10b' - ), - storageRoot: hexStringToBytes( - 'cafd881ab193703b83816c49ff6c2bf6ba6f464a1be560c42106128c8dbc35e7' - ), - }) - - const res3 = await stateManager.getAccount(address) - - st.equal( - bytesToHex(res3.codeHash), - 'd748bf26ab37599c944babfdbeecf6690801bd61bf2670efb0a34adfc6dca10b' - ) - st.equal( - bytesToHex(res3.storageRoot), - 'cafd881ab193703b83816c49ff6c2bf6ba6f464a1be560c42106128c8dbc35e7' - ) - - st.end() - }) - - t.test( - 'should modify account fields correctly on previously non-existent account', - async (st) => { - const stateManager = new DefaultStateManager() - const address = new Address(hexStringToBytes('a94f5374fce5edbc8e2a8697c15331677e6ebf0b')) - - await stateManager.modifyAccountFields(address, { balance: BigInt(1234) }) - const res1 = await stateManager.getAccount(address) - st.equal(res1.balance, BigInt(0x4d2)) - - await stateManager.modifyAccountFields(address, { nonce: BigInt(1) }) - const res2 = await stateManager.getAccount(address) - st.equal(res2.nonce, BigInt(1)) - - const newCodeHash = hexStringToBytes( - 'd748bf26ab37599c944babfdbeecf6690801bd61bf2670efb0a34adfc6dca10b' - ) - const newStorageRoot = hexStringToBytes( - 'cafd881ab193703b83816c49ff6c2bf6ba6f464a1be560c42106128c8dbc35e7' - ) - await stateManager.modifyAccountFields(address, { - codeHash: newCodeHash, - storageRoot: newStorageRoot, - }) - - const res3 = await stateManager.getAccount(address) - st.ok(equalsBytes(res3.codeHash, newCodeHash)) - st.ok(equalsBytes(res3.storageRoot, newStorageRoot)) - st.end() - } - ) - - t.test('should dump storage', async (st) => { - const stateManager = new DefaultStateManager() - const address = new Address(hexStringToBytes('a94f5374fce5edbc8e2a8697c15331677e6ebf0b')) - const account = createAccount() - - await stateManager.putAccount(address, account) - - const key = hexStringToBytes( - '0x1234567890123456789012345678901234567890123456789012345678901234' - ) - const value = hexStringToBytes('0x0a') // We used this value as its RLP encoding is also 0a - await stateManager.putContractStorage(address, key, value) - - const data = await stateManager.dumpStorage(address) - const expect = { [bytesToHex(keccak256(key))]: '0a' } - st.deepEqual(data, expect, 'should dump storage value') - - st.end() - }) - - t.test("should validate the key's length when modifying a contract's storage", async (st) => { - const stateManager = new DefaultStateManager() - const address = new Address(hexStringToBytes('a94f5374fce5edbc8e2a8697c15331677e6ebf0b')) - try { - await stateManager.putContractStorage(address, new Uint8Array(12), hexStringToBytes('0x1231')) - } catch (e: any) { - st.equal(e.message, 'Storage key must be 32 bytes long') - st.end() - return - } - - st.fail('Should have failed') - st.end() - }) - - t.test("should validate the key's length when reading a contract's storage", async (st) => { - const stateManager = new DefaultStateManager() - const address = new Address(hexStringToBytes('a94f5374fce5edbc8e2a8697c15331677e6ebf0b')) - try { - await stateManager.getContractStorage(address, new Uint8Array(12)) - } catch (e: any) { - st.equal(e.message, 'Storage key must be 32 bytes long') - st.end() - return - } - - st.fail('Should have failed') - st.end() - }) - - t.test('should store codehashes using a prefix', async (st) => { - /* - This test is mostly an example of why a code prefix is necessary - I an address, we put two storage values. The preimage of the (storage trie) root hash is known - This preimage is used as codeHash - - NOTE: Currently, the only problem which this code prefix fixes, is putting 0x80 as contract code - -> This hashes to the empty trie node hash (0x80 = RLP([])), so keccak256(0x80) = empty trie node hash - -> Therefore, each empty state trie now points to 0x80, which is not a valid trie node, which crashes @ethereumjs/trie - */ - - // Setup - const stateManager = new DefaultStateManager() - const codeStateManager = new DefaultStateManager() - const address1 = new Address(hexStringToBytes('a94f5374fce5edbc8e2a8697c15331677e6ebf0b')) - const key1 = hexStringToBytes('00'.repeat(32)) - const key2 = hexStringToBytes('00'.repeat(31) + '01') - - await stateManager.putContractStorage(address1, key1, key2) - await stateManager.putContractStorage(address1, key2, key2) - const root = await stateManager.getStateRoot() - // @ts-expect-error - const rawNode = await stateManager._trie._db.get(root) - - await codeStateManager.putContractCode(address1, rawNode!) - - let codeSlot1 = await codeStateManager.getContractStorage(address1, key1) - let codeSlot2 = await codeStateManager.getContractStorage(address1, key2) - - st.ok(codeSlot1.length === 0, 'slot 0 is empty') - st.ok(codeSlot2.length === 0, 'slot 1 is empty') - - const code = await codeStateManager.getContractCode(address1) - st.ok(code.length > 0, 'code deposited correctly') - - const slot1 = await stateManager.getContractStorage(address1, key1) - const slot2 = await stateManager.getContractStorage(address1, key2) - - st.ok(slot1.length > 0, 'storage key0 deposited correctly') - st.ok(slot2.length > 0, 'storage key1 deposited correctly') - - let slotCode = await stateManager.getContractCode(address1) - st.ok(slotCode.length === 0, 'code cannot be loaded') - - // Checks by either setting state root to codeHash, or codeHash to stateRoot - // The knowledge of the tries should not change - let account = await stateManager.getAccount(address1) - account.codeHash = root - - await stateManager.putAccount(address1, account) - - slotCode = await stateManager.getContractCode(address1) - st.ok(slotCode.length === 0, 'code cannot be loaded') // This test fails if no code prefix is used - - account = await codeStateManager.getAccount(address1) - account.storageRoot = root - - await codeStateManager.putAccount(address1, account) - - codeSlot1 = await codeStateManager.getContractStorage(address1, key1) - codeSlot2 = await codeStateManager.getContractStorage(address1, key2) - - st.ok(codeSlot1.length === 0, 'slot 0 is empty') - st.ok(codeSlot2.length === 0, 'slot 1 is empty') - - st.end() - }) -}) - -tape('StateManager - Contract code', (tester) => { - const it = tester.test - it('should set and get code', async (t) => { - const stateManager = new DefaultStateManager() - const address = new Address(hexStringToBytes('a94f5374fce5edbc8e2a8697c15331677e6ebf0b')) - const code = hexStringToBytes( - '73095e7baea6a6c7c4c2dfeb977efac326af552d873173095e7baea6a6c7c4c2dfeb977efac326af552d873157' - ) - const raw = { - nonce: '0x0', - balance: '0x03e7', - stateRoot: '0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421', - codeHash: '0xb30fb32201fe0486606ad451e1a61e2ae1748343cd3d411ed992ffcc0774edd4', - } - const account = Account.fromAccountData(raw) - await stateManager.putAccount(address, account) - await stateManager.putContractCode(address, code) - const codeRetrieved = await stateManager.getContractCode(address) - t.ok(equalsBytes(code, codeRetrieved)) - t.end() - }) - - it('should not get code if is not contract', async (t) => { - const stateManager = new DefaultStateManager() - const address = new Address(hexStringToBytes('a94f5374fce5edbc8e2a8697c15331677e6ebf0b')) - const raw = { - nonce: '0x0', - balance: '0x03e7', - } - const account = Account.fromAccountData(raw) - await stateManager.putAccount(address, account) - const code = await stateManager.getContractCode(address) - t.ok(equalsBytes(code, new Uint8Array(0))) - t.end() - }) - - it('should set empty code', async (t) => { - const stateManager = new DefaultStateManager() - const address = new Address(hexStringToBytes('a94f5374fce5edbc8e2a8697c15331677e6ebf0b')) - const raw = { - nonce: '0x0', - balance: '0x03e7', - } - const account = Account.fromAccountData(raw) - const code = new Uint8Array(0) - await stateManager.putAccount(address, account) - await stateManager.putContractCode(address, code) - const codeRetrieved = await stateManager.getContractCode(address) - t.ok(equalsBytes(codeRetrieved, new Uint8Array(0))) - t.end() - }) - - it('should prefix codehashes by default', async (t) => { - const stateManager = new DefaultStateManager() - const address = new Address(hexStringToBytes('a94f5374fce5edbc8e2a8697c15331677e6ebf0b')) - const code = hexStringToBytes('80') - await stateManager.putContractCode(address, code) - const codeRetrieved = await stateManager.getContractCode(address) - t.ok(equalsBytes(codeRetrieved, code)) - t.end() - }) - - it('should not prefix codehashes if prefixCodeHashes = false', async (t) => { - const stateManager = new DefaultStateManager({ - prefixCodeHashes: false, - }) - const address = new Address(hexStringToBytes('a94f5374fce5edbc8e2a8697c15331677e6ebf0b')) - const code = hexStringToBytes('80') - try { - await stateManager.putContractCode(address, code) - t.fail('should throw') - } catch (e) { - t.pass('successfully threw') - } - t.end() - }) -}) - -tape('StateManager - Contract storage', (tester) => { - const it = tester.test - - it('should throw on storage values larger than 32 bytes', async (t) => { - t.plan(1) - const stateManager = new DefaultStateManager() - const address = Address.zero() - const key = zeros(32) - const value = hexStringToBytes('aa'.repeat(33)) - try { - await stateManager.putContractStorage(address, key, value) - t.fail('did not throw') - } catch (e: any) { - t.pass('threw on trying to set storage values larger than 32 bytes') - } - t.end() - }) - - it('should strip zeros of storage values', async (t) => { - const stateManager = new DefaultStateManager() - const address = Address.zero() - - const key0 = zeros(32) - const value0 = hexStringToBytes('00' + 'aa'.repeat(30)) // put a value of 31-bytes length with a leading zero byte - const expect0 = unpadBytes(value0) - await stateManager.putContractStorage(address, key0, value0) - const slot0 = await stateManager.getContractStorage(address, key0) - t.ok(equalsBytes(slot0, expect0), 'value of 31 bytes padded correctly') - - const key1 = concatBytes(zeros(31), hexStringToBytes('01')) - const value1 = hexStringToBytes('0000' + 'aa'.repeat(1)) // put a value of 1-byte length with two leading zero bytes - const expect1 = unpadBytes(value1) - await stateManager.putContractStorage(address, key1, value1) - const slot1 = await stateManager.getContractStorage(address, key1) - - t.ok(equalsBytes(slot1, expect1), 'value of 1 byte padded correctly') - t.end() - }) - - it('should delete storage values which only consist of zero bytes', async (t) => { - const address = Address.zero() - const key = zeros(32) - const startValue = hexStringToBytes('01') - - const zeroLengths = [0, 1, 31, 32] // checks for arbitrary-length zeros - t.plan(zeroLengths.length) - - for (const length of zeroLengths) { - const stateManager = new DefaultStateManager() - const value = zeros(length) - await stateManager.putContractStorage(address, key, startValue) - const currentValue = await stateManager.getContractStorage(address, key) - if (!equalsBytes(currentValue, startValue)) { - // sanity check - t.fail('contract value not set correctly') - } else { - // delete the value - await stateManager.putContractStorage(address, key, value) - const deleted = await stateManager.getContractStorage(address, key) - t.ok(equalsBytes(deleted, zeros(0)), 'the storage key should be deleted') - } - } - t.end() - }) - - it('should not strip trailing zeros', async (t) => { - const address = Address.zero() - const key = zeros(32) - const value = hexToBytes('0000aabb00') - const expect = hexToBytes('aabb00') - const stateManager = new DefaultStateManager() - await stateManager.putContractStorage(address, key, value) - const contractValue = await stateManager.getContractStorage(address, key) - t.ok(equalsBytes(contractValue, expect), 'trailing zeros are not stripped') - t.end() - }) -}) diff --git a/packages/statemanager/test/stateManager.storage.spec.ts b/packages/statemanager/test/stateManager.storage.spec.ts new file mode 100644 index 0000000000..cfbafb4790 --- /dev/null +++ b/packages/statemanager/test/stateManager.storage.spec.ts @@ -0,0 +1,158 @@ +import { Address, hexStringToBytes, unpadBytes, zeros } from '@ethereumjs/util' +import { keccak256 } from 'ethereum-cryptography/keccak' +import { bytesToHex, concatBytes, equalsBytes } from 'ethereum-cryptography/utils' +import * as tape from 'tape' +// explicitly import `inherits` to fix karma-typescript issue +// eslint-disable-next-line @typescript-eslint/no-unused-vars +import { inherits } from 'util' + +import { DefaultStateManager } from '../src' + +import { createAccount } from './util' + +tape('StateManager -> Storage', (t) => { + for (const storageCacheOpts of [{ deactivate: false }, { deactivate: true }]) { + t.test('should dump storage', async (st) => { + const stateManager = new DefaultStateManager({ storageCacheOpts }) + const address = new Address(hexStringToBytes('a94f5374fce5edbc8e2a8697c15331677e6ebf0b')) + const account = createAccount() + + await stateManager.putAccount(address, account) + + const key = hexStringToBytes( + '1234567890123456789012345678901234567890123456789012345678901234' + ) + const value = hexStringToBytes('0a') // We used this value as its RLP encoding is also 0a + await stateManager.putContractStorage(address, key, value) + + const data = await stateManager.dumpStorage(address) + const expect = { [bytesToHex(keccak256(key))]: '0a' } + st.deepEqual(data, expect, 'should dump storage value') + + st.end() + }) + + t.test("should validate the key's length when modifying a contract's storage", async (st) => { + const stateManager = new DefaultStateManager({ storageCacheOpts }) + const address = new Address(hexStringToBytes('a94f5374fce5edbc8e2a8697c15331677e6ebf0b')) + const account = createAccount() + await stateManager.putAccount(address, account) + + try { + await stateManager.putContractStorage(address, new Uint8Array(12), hexStringToBytes('1231')) + } catch (e: any) { + st.equal(e.message, 'Storage key must be 32 bytes long') + st.end() + return + } + + st.fail('Should have failed') + st.end() + }) + + t.test("should validate the key's length when reading a contract's storage", async (st) => { + const stateManager = new DefaultStateManager({ storageCacheOpts }) + const address = new Address(hexStringToBytes('a94f5374fce5edbc8e2a8697c15331677e6ebf0b')) + const account = createAccount() + await stateManager.putAccount(address, account) + + try { + await stateManager.getContractStorage(address, new Uint8Array(12)) + } catch (e: any) { + st.equal(e.message, 'Storage key must be 32 bytes long') + st.end() + return + } + + st.fail('Should have failed') + st.end() + }) + + t.test('should throw on storage values larger than 32 bytes', async (st) => { + st.plan(1) + const stateManager = new DefaultStateManager({ storageCacheOpts }) + const address = Address.zero() + const account = createAccount() + await stateManager.putAccount(address, account) + + const key = zeros(32) + const value = hexStringToBytes('aa'.repeat(33)) + try { + await stateManager.putContractStorage(address, key, value) + st.fail('did not throw') + } catch (e: any) { + st.pass('threw on trying to set storage values larger than 32 bytes') + } + st.end() + }) + + t.test('should strip zeros of storage values', async (st) => { + const stateManager = new DefaultStateManager({ storageCacheOpts }) + const address = Address.zero() + const account = createAccount() + await stateManager.putAccount(address, account) + + const key0 = zeros(32) + const value0 = hexStringToBytes('00' + 'aa'.repeat(30)) // put a value of 31-bytes length with a leading zero byte + const expect0 = unpadBytes(value0) + await stateManager.putContractStorage(address, key0, value0) + const slot0 = await stateManager.getContractStorage(address, key0) + st.ok(equalsBytes(slot0, expect0), 'value of 31 bytes padded correctly') + + const key1 = concatBytes(zeros(31), hexStringToBytes('01')) + const value1 = hexStringToBytes('0000' + 'aa'.repeat(1)) // put a value of 1-byte length with two leading zero bytes + const expect1 = unpadBytes(value1) + await stateManager.putContractStorage(address, key1, value1) + const slot1 = await stateManager.getContractStorage(address, key1) + + st.ok(equalsBytes(slot1, expect1), 'value of 1 byte padded correctly') + st.end() + }) + + t.test('should delete storage values which only consist of zero bytes', async (st) => { + const address = Address.zero() + const key = zeros(32) + + const startValue = hexStringToBytes('01') + + const zeroLengths = [0, 1, 31, 32] // checks for arbitrary-length zeros + st.plan(zeroLengths.length) + + for (const length of zeroLengths) { + const stateManager = new DefaultStateManager({ storageCacheOpts }) + const account = createAccount() + await stateManager.putAccount(address, account) + + const value = zeros(length) + await stateManager.putContractStorage(address, key, startValue) + const currentValue = await stateManager.getContractStorage(address, key) + if (!equalsBytes(currentValue, startValue)) { + // sanity check + st.fail('contract value not set correctly') + } else { + // delete the value + await stateManager.putContractStorage(address, key, value) + const deleted = await stateManager.getContractStorage(address, key) + st.ok(equalsBytes(deleted, zeros(0)), 'the storage key should be deleted') + } + } + st.end() + }) + + t.test('should not strip trailing zeros', async (st) => { + const stateManager = new DefaultStateManager({ storageCacheOpts }) + const address = Address.zero() + const account = createAccount() + await stateManager.putAccount(address, account) + + const key = zeros(32) + const value = hexStringToBytes('0000aabb00') + const expect = hexStringToBytes('aabb00') + + await stateManager.putContractStorage(address, key, value) + const contractValue = await stateManager.getContractStorage(address, key) + st.ok(equalsBytes(contractValue, expect), 'trailing zeros are not stripped') + st.end() + }) + } +}) diff --git a/packages/vm/examples/helpers/account-utils.ts b/packages/vm/examples/helpers/account-utils.ts index 9d806f5746..01e5d743f0 100644 --- a/packages/vm/examples/helpers/account-utils.ts +++ b/packages/vm/examples/helpers/account-utils.ts @@ -20,5 +20,9 @@ export const insertAccount = async (vm: VM, address: Address) => { export const getAccountNonce = async (vm: VM, accountPrivateKey: Uint8Array) => { const address = Address.fromPrivateKey(accountPrivateKey) const account = await vm.stateManager.getAccount(address) - return account.nonce + if (account) { + return account.nonce + } else { + return BigInt(0) + } } diff --git a/packages/vm/examples/run-solidity-contract.ts b/packages/vm/examples/run-solidity-contract.ts index 1d45d84372..6a79bf1dea 100644 --- a/packages/vm/examples/run-solidity-contract.ts +++ b/packages/vm/examples/run-solidity-contract.ts @@ -212,10 +212,10 @@ async function main() { const createdAccount = await vm.stateManager.getAccount(contractAddress) console.log('-------results-------') - console.log('nonce: ' + createdAccount.nonce.toString()) - console.log('balance in wei: ', createdAccount.balance.toString()) - console.log('storageRoot: 0x' + bytesToHex(createdAccount.storageRoot)) - console.log('codeHash: 0x' + bytesToHex(createdAccount.codeHash)) + console.log('nonce: ' + createdAccount!.nonce.toString()) + console.log('balance in wei: ', createdAccount!.balance.toString()) + console.log('storageRoot: 0x' + bytesToHex(createdAccount!.storageRoot)) + console.log('codeHash: 0x' + bytesToHex(createdAccount!.codeHash)) console.log('---------------------') console.log('Everything ran correctly!') diff --git a/packages/vm/src/eei/eei.ts b/packages/vm/src/eei/eei.ts index 4b0dba48fb..b68876418a 100644 --- a/packages/vm/src/eei/eei.ts +++ b/packages/vm/src/eei/eei.ts @@ -1,4 +1,4 @@ -import { bytesToBigInt } from '@ethereumjs/util' +import { Account, bytesToBigInt } from '@ethereumjs/util' import { VmState } from './vmState' @@ -39,7 +39,10 @@ export class EEI extends VmState implements EEIInterface { * @param address - Address of account */ async getExternalBalance(address: Address): Promise { - const account = await this.getAccount(address) + let account = await this.getAccount(address) + if (!account) { + account = new Account() + } return account.balance } diff --git a/packages/vm/src/eei/vmState.ts b/packages/vm/src/eei/vmState.ts index 48c2c40ac8..233e11a719 100644 --- a/packages/vm/src/eei/vmState.ts +++ b/packages/vm/src/eei/vmState.ts @@ -132,7 +132,7 @@ export class VmState implements EVMStateAccess { } } - async getAccount(address: Address): Promise { + async getAccount(address: Address): Promise { return this._stateManager.getAccount(address) } @@ -180,11 +180,11 @@ export class VmState implements EVMStateAccess { return this._stateManager.accountExists(address) } - async setStateRoot(stateRoot: Uint8Array): Promise { + async setStateRoot(stateRoot: Uint8Array, clearCache: boolean = true): Promise { if (this._checkpointCount !== 0) { throw new Error('Cannot set state root with uncommitted checkpoints') } - return this._stateManager.setStateRoot(stateRoot) + return this._stateManager.setStateRoot(stateRoot, clearCache) } async getStateRoot(): Promise { @@ -267,6 +267,7 @@ export class VmState implements EVMStateAccess { } await this._stateManager.flush() // If any empty accounts are put, these should not be marked as touched (when first tx is ran, this account is deleted when it cleans up the accounts) + // TODO: not 100% sure if to keep this line or not along cache refactor rebase, 2023-04-11 this.touchedJournal.clear() } @@ -279,7 +280,7 @@ export class VmState implements EVMStateAccess { const touchedArray = Array.from(this.touchedJournal.journal) for (const addressHex of touchedArray) { const address = new Address(hexToBytes(addressHex)) - const empty = await this.accountIsEmpty(address) + const empty = await this.accountIsEmptyOrNonExistent(address) if (empty) { await this._stateManager.deleteAccount(address) if (this.DEBUG) { @@ -478,7 +479,11 @@ export class VmState implements EVMStateAccess { * EIP-161 (https://eips.ethereum.org/EIPS/eip-161). * @param address - Address to check */ - async accountIsEmpty(address: Address): Promise { - return this._stateManager.accountIsEmpty(address) + async accountIsEmptyOrNonExistent(address: Address): Promise { + const account = await this._stateManager.getAccount(address) + if (account === undefined || account.isEmpty()) { + return true + } + return false } } diff --git a/packages/vm/src/runBlock.ts b/packages/vm/src/runBlock.ts index fcddca13ad..3c52926ce9 100644 --- a/packages/vm/src/runBlock.ts +++ b/packages/vm/src/runBlock.ts @@ -42,6 +42,7 @@ const DAORefundContract = DAOConfig.DAORefundContract export async function runBlock(this: VM, opts: RunBlockOpts): Promise { const state = this.eei const { root } = opts + const clearCache = opts.clearCache ?? true let { block } = opts const generateFields = opts.generate === true @@ -80,7 +81,7 @@ export async function runBlock(this: VM, opts: RunBlockOpts): Promise { - const account = await state.getAccount(address) + let account = await state.getAccount(address) + if (account === undefined) { + account = new Account() + } account.balance += reward await state.putAccount(address, account) return account @@ -435,12 +441,18 @@ async function _applyDAOHardfork(state: EVMStateAccess) { if ((await state.accountExists(DAORefundContractAddress)) === false) { await state.putAccount(DAORefundContractAddress, new Account()) } - const DAORefundAccount = await state.getAccount(DAORefundContractAddress) + let DAORefundAccount = await state.getAccount(DAORefundContractAddress) + if (DAORefundAccount === undefined) { + DAORefundAccount = new Account() + } for (const addr of DAOAccountList) { // retrieve the account and add it to the DAO's Refund accounts' balance. const address = new Address(hexToBytes(addr)) - const account = await state.getAccount(address) + let account = await state.getAccount(address) + if (account === undefined) { + account = new Account() + } DAORefundAccount.balance += account.balance // clear the accounts' balance account.balance = BigInt(0) diff --git a/packages/vm/src/runTx.ts b/packages/vm/src/runTx.ts index 7c3d8b5ece..43b32f2ff1 100644 --- a/packages/vm/src/runTx.ts +++ b/packages/vm/src/runTx.ts @@ -1,7 +1,14 @@ import { Block, getDataGasPrice } from '@ethereumjs/block' import { ConsensusType, Hardfork } from '@ethereumjs/common' import { BlobEIP4844Transaction, Capability } from '@ethereumjs/tx' -import { Address, KECCAK256_NULL, bytesToPrefixedHexString, short, toBytes } from '@ethereumjs/util' +import { + Account, + Address, + KECCAK256_NULL, + bytesToPrefixedHexString, + short, + toBytes, +} from '@ethereumjs/util' import { debug as createDebugLogger } from 'debug' import { bytesToHex, equalsBytes, hexToBytes } from 'ethereum-cryptography/utils' @@ -262,8 +269,13 @@ async function _runTx(this: VM, opts: RunTxOpts): Promise { // Check from account's balance and nonce let fromAccount = await state.getAccount(caller) + if (fromAccount === undefined) { + fromAccount = new Account() + } const { nonce, balance } = fromAccount - debug(`Sender's pre-tx balance is ${balance}`) + if (this.DEBUG) { + debug(`Sender's pre-tx balance is ${balance}`) + } // EIP-3607: Reject transactions from senders with deployed code if ( this._common.isActivatedEIP(3607) === true && @@ -482,6 +494,9 @@ async function _runTx(this: VM, opts: RunTxOpts): Promise { // Update sender's balance fromAccount = await state.getAccount(caller) + if (fromAccount === undefined) { + fromAccount = new Account() + } const actualTxCost = results.totalGasSpent * gasPrice const txCostDiff = txCost - actualTxCost fromAccount.balance += txCostDiff @@ -500,7 +515,10 @@ async function _runTx(this: VM, opts: RunTxOpts): Promise { miner = block.header.coinbase } - const minerAccount = await state.getAccount(miner) + let minerAccount = await state.getAccount(miner) + if (minerAccount === undefined) { + minerAccount = new Account() + } // add the amount spent on gas to the miner's account results.minerValue = this._common.isActivatedEIP(1559) === true diff --git a/packages/vm/src/types.ts b/packages/vm/src/types.ts index 727f2be983..ff498c6250 100644 --- a/packages/vm/src/types.ts +++ b/packages/vm/src/types.ts @@ -208,6 +208,14 @@ export interface RunBlockOpts { * Root of the state trie */ root?: Uint8Array + /** + * Clearing the StateManager cache. + * + * If state root is not reset for whatever reason this can be set to `false` for better performance. + * + * Default: true + */ + clearCache?: boolean /** * Whether to generate the stateRoot and other related fields. * If `true`, `runBlock` will set the fields `stateRoot`, `receiptTrie`, `gasUsed`, and `bloom` (logs bloom) after running the block. diff --git a/packages/vm/src/vm.ts b/packages/vm/src/vm.ts index 678e5b4ee8..c3e89a4e43 100644 --- a/packages/vm/src/vm.ts +++ b/packages/vm/src/vm.ts @@ -179,10 +179,11 @@ export class VM { // put 1 wei in each of the precompiles in order to make the accounts non-empty and thus not have them deduct `callNewAccount` gas. for (const [addressStr] of getActivePrecompiles(this._common)) { const address = new Address(hexToBytes(addressStr)) - const account = await this.eei.getAccount(address) + let account = await this.eei.getAccount(address) // Only do this if it is not overridden in genesis // Note: in the case that custom genesis has storage fields, this is preserved - if (account.isEmpty() === true) { + if (account === undefined) { + account = new Account() const newAccount = Account.fromAccountData({ balance: 1, storageRoot: account.storageRoot, diff --git a/packages/vm/test/api/EIPs/eip-1559-FeeMarket.spec.ts b/packages/vm/test/api/EIPs/eip-1559-FeeMarket.spec.ts index 71e513012f..dce6f34066 100644 --- a/packages/vm/test/api/EIPs/eip-1559-FeeMarket.spec.ts +++ b/packages/vm/test/api/EIPs/eip-1559-FeeMarket.spec.ts @@ -5,7 +5,7 @@ import { FeeMarketEIP1559Transaction, Transaction, } from '@ethereumjs/tx' -import { Address, bigIntToBytes, privateToAddress, setLengthLeft } from '@ethereumjs/util' +import { Account, Address, bigIntToBytes, privateToAddress, setLengthLeft } from '@ethereumjs/util' import { hexToBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' @@ -77,10 +77,11 @@ tape('EIP1559 tests', (t) => { ) const block = makeBlock(GWEI, tx, 2) const vm = await VM.create({ common }) + await vm.stateManager.putAccount(sender, new Account()) let account = await vm.stateManager.getAccount(sender) const balance = GWEI * BigInt(21000) * BigInt(10) - account.balance = balance - await vm.stateManager.putAccount(sender, account) + account!.balance = balance + await vm.stateManager.putAccount(sender, account!) const results = await vm.runTx({ tx: block.transactions[0], block, @@ -98,9 +99,9 @@ tape('EIP1559 tests', (t) => { let miner = await vm.stateManager.getAccount(coinbase) - st.equal(miner.balance, expectedMinerBalance, 'miner balance correct') + st.equal(miner!.balance, expectedMinerBalance, 'miner balance correct') account = await vm.stateManager.getAccount(sender) - st.equal(account.balance, expectedAccountBalance, 'account balance correct') + st.equal(account!.balance, expectedAccountBalance, 'account balance correct') st.equal(results.amountSpent, expectedCost, 'reported cost correct') const tx2 = new AccessListEIP2930Transaction( @@ -126,9 +127,9 @@ tape('EIP1559 tests', (t) => { miner = await vm.stateManager.getAccount(coinbase) - st.equal(miner.balance, expectedMinerBalance, 'miner balance correct') + st.equal(miner!.balance, expectedMinerBalance, 'miner balance correct') account = await vm.stateManager.getAccount(sender) - st.equal(account.balance, expectedAccountBalance, 'account balance correct') + st.equal(account!.balance, expectedAccountBalance, 'account balance correct') st.equal(results2.amountSpent, expectedCost, 'reported cost correct') const tx3 = new Transaction( @@ -154,9 +155,9 @@ tape('EIP1559 tests', (t) => { miner = await vm.stateManager.getAccount(coinbase) - st.equal(miner.balance, expectedMinerBalance, 'miner balance correct') + st.equal(miner!.balance, expectedMinerBalance, 'miner balance correct') account = await vm.stateManager.getAccount(sender) - st.equal(account.balance, expectedAccountBalance, 'account balance correct') + st.equal(account!.balance, expectedAccountBalance, 'account balance correct') st.equal(results3.amountSpent, expectedCost, 'reported cost correct') st.end() diff --git a/packages/vm/test/api/EIPs/eip-3074-authcall.spec.ts b/packages/vm/test/api/EIPs/eip-3074-authcall.spec.ts index 33de708963..48fc52b506 100644 --- a/packages/vm/test/api/EIPs/eip-3074-authcall.spec.ts +++ b/packages/vm/test/api/EIPs/eip-3074-authcall.spec.ts @@ -3,6 +3,7 @@ import { Chain, Common, Hardfork } from '@ethereumjs/common' import { ERROR } from '@ethereumjs/evm/dist/exceptions' import { Transaction } from '@ethereumjs/tx' import { + Account, Address, bigIntToBytes, bytesToBigInt, @@ -226,9 +227,10 @@ tape('EIP-3074 AUTH', (t) => { gasPrice: 10, }).sign(callerPrivateKey) + await vm.stateManager.putAccount(callerAddress, new Account()) const account = await vm.stateManager.getAccount(callerAddress) - account.balance = BigInt(10000000) - await vm.stateManager.putAccount(callerAddress, account) + account!.balance = BigInt(10000000) + await vm.stateManager.putAccount(callerAddress, account!) const result = await vm.runTx({ tx, block, skipHardForkValidation: true }) const buf = result.execResult.returnValue.slice(31) @@ -249,9 +251,10 @@ tape('EIP-3074 AUTH', (t) => { gasPrice: 10, }).sign(callerPrivateKey) + await vm.stateManager.putAccount(callerAddress, new Account()) const account = await vm.stateManager.getAccount(callerAddress) - account.balance = BigInt(10000000) - await vm.stateManager.putAccount(callerAddress, account) + account!.balance = BigInt(10000000) + await vm.stateManager.putAccount(callerAddress, account!) const result = await vm.runTx({ tx, block, skipHardForkValidation: true }) const buf = result.execResult.returnValue @@ -273,9 +276,10 @@ tape('EIP-3074 AUTH', (t) => { gasPrice: 10, }).sign(callerPrivateKey) + await vm.stateManager.putAccount(callerAddress, new Account()) const account = await vm.stateManager.getAccount(callerAddress) - account.balance = BigInt(10000000) - await vm.stateManager.putAccount(callerAddress, account) + account!.balance = BigInt(10000000) + await vm.stateManager.putAccount(callerAddress, account!) const result = await vm.runTx({ tx, block, skipHardForkValidation: true }) const buf = result.execResult.returnValue @@ -295,9 +299,10 @@ tape('EIP-3074 AUTH', (t) => { gasPrice: 10, }).sign(callerPrivateKey) + await vm.stateManager.putAccount(callerAddress, new Account()) const account = await vm.stateManager.getAccount(callerAddress) - account.balance = BigInt(10000000) - await vm.stateManager.putAccount(callerAddress, account) + account!.balance = BigInt(10000000) + await vm.stateManager.putAccount(callerAddress, account!) const result = await vm.runTx({ tx, block, skipHardForkValidation: true }) st.equal(result.execResult.exceptionError?.error, ERROR.AUTH_INVALID_S, 'threw correct error') @@ -321,9 +326,10 @@ tape('EIP-3074 AUTH', (t) => { gasPrice: 10, }).sign(callerPrivateKey) + await vm.stateManager.putAccount(callerAddress, new Account()) const account = await vm.stateManager.getAccount(callerAddress) - account.balance = BigInt(10000000) - await vm.stateManager.putAccount(callerAddress, account) + account!.balance = BigInt(10000000) + await vm.stateManager.putAccount(callerAddress, account!) const result = await vm.runTx({ tx, block, skipHardForkValidation: true }) const buf = result.execResult.returnValue.slice(31) @@ -346,9 +352,10 @@ tape('EIP-3074 AUTH', (t) => { gasPrice: 10, }).sign(callerPrivateKey) + await vm.stateManager.putAccount(callerAddress, new Account()) const account = await vm.stateManager.getAccount(callerAddress) - account.balance = BigInt(10000000) - await vm.stateManager.putAccount(callerAddress, account) + account!.balance = BigInt(10000000) + await vm.stateManager.putAccount(callerAddress, account!) const result = await vm.runTx({ tx, block, skipHardForkValidation: true }) const buf = result.execResult.returnValue.slice(31) @@ -368,9 +375,10 @@ tape('EIP-3074 AUTH', (t) => { gasPrice: 10, }).sign(callerPrivateKey) + await vm.stateManager.putAccount(callerAddress, new Account()) const account = await vm.stateManager.getAccount(callerAddress) - account.balance = BigInt(20000000) - await vm.stateManager.putAccount(callerAddress, account) + account!.balance = BigInt(20000000) + await vm.stateManager.putAccount(callerAddress, account!) const result = await vm.runTx({ tx, block, skipHardForkValidation: true }) @@ -413,8 +421,9 @@ async function setupVM(code: Uint8Array) { const vm = await VM.create({ common: common.copy() }) await vm.stateManager.putContractCode(contractAddress, code) await vm.stateManager.putContractCode(contractStorageAddress, STORECALLER) + await vm.stateManager.putAccount(callerAddress, new Account()) const account = await vm.stateManager.getAccount(callerAddress) - account.balance = PREBALANCE + account!.balance = PREBALANCE await vm.stateManager.modifyAccountFields(callerAddress, { balance: PREBALANCE }) return vm } @@ -623,13 +632,13 @@ tape('EIP-3074 AUTHCALL', (t) => { const expectedBalance = PREBALANCE - result.amountSpent - value const account = await vm.stateManager.getAccount(callerAddress) - st.equal(account.balance, expectedBalance, 'caller balance ok') + st.equal(account!.balance, expectedBalance, 'caller balance ok') const contractAccount = await vm.stateManager.getAccount(contractAddress) - st.equal(contractAccount.balance, 2n, 'contract balance ok') + st.equal(contractAccount!.balance, 2n, 'contract balance ok') const contractStorageAccount = await vm.stateManager.getAccount(contractStorageAddress) - st.equal(contractStorageAccount.balance, 1n, 'storage balance ok') + st.equal(contractStorageAccount!.balance, 1n, 'storage balance ok') } ) diff --git a/packages/vm/test/api/EIPs/eip-3529.spec.ts b/packages/vm/test/api/EIPs/eip-3529.spec.ts index 2e221a0c5c..c242e4df51 100644 --- a/packages/vm/test/api/EIPs/eip-3529.spec.ts +++ b/packages/vm/test/api/EIPs/eip-3529.spec.ts @@ -1,6 +1,6 @@ import { Chain, Common, Hardfork } from '@ethereumjs/common' import { Transaction } from '@ethereumjs/tx' -import { Address } from '@ethereumjs/util' +import { Account, Address } from '@ethereumjs/util' import { hexToBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' @@ -131,6 +131,7 @@ tape('EIP-3529 tests', (t) => { for (const testCase of testCases) { const code = hexToBytes((testCase.code + '00').slice(2)) // add a STOP opcode (0 gas) so we can find the gas used / effective gas + await vm.stateManager.putAccount(address, new Account()) await vm.stateManager.putContractStorage( address, key, @@ -203,6 +204,7 @@ tape('EIP-3529 tests', (t) => { for (let i = 0; i < 100; i++) { const key = hexToBytes(i.toString(16).padStart(64, '0')) + await vm.stateManager.putAccount(address, new Account()) await vm.stateManager.putContractStorage(address, key, value) const hex = i.toString(16).padStart(2, '0') // push 0 push sstore diff --git a/packages/vm/test/api/EIPs/eip-3540-evm-object-format.spec.ts b/packages/vm/test/api/EIPs/eip-3540-evm-object-format.spec.ts index 1bfc0a075e..6602722b17 100644 --- a/packages/vm/test/api/EIPs/eip-3540-evm-object-format.spec.ts +++ b/packages/vm/test/api/EIPs/eip-3540-evm-object-format.spec.ts @@ -1,7 +1,7 @@ import { Chain, Common, Hardfork } from '@ethereumjs/common' import { EOF } from '@ethereumjs/evm/dist/eof' import { FeeMarketEIP1559Transaction } from '@ethereumjs/tx' -import { Address, concatBytesNoTypeCheck, privateToAddress } from '@ethereumjs/util' +import { Account, Address, concatBytesNoTypeCheck, privateToAddress } from '@ethereumjs/util' import { hexToBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' @@ -74,10 +74,11 @@ tape('EIP 3540 tests', (t) => { eips: [3540], }) const vm = await VM.create({ common }) + await vm.stateManager.putAccount(sender, new Account()) const account = await vm.stateManager.getAccount(sender) const balance = GWEI * BigInt(21000) * BigInt(10000000) - account.balance = balance - await vm.stateManager.putAccount(sender, account) + account!.balance = balance + await vm.stateManager.putAccount(sender, account!) let data = '0x67' + 'EF0001' + '01000100' + '00' + '60005260086018F3' let res = await runTx(vm, data, 0) @@ -90,10 +91,11 @@ tape('EIP 3540 tests', (t) => { t.test('invalid EOF format / contract creation', async (st) => { const vm = await VM.create({ common }) + await vm.stateManager.putAccount(sender, new Account()) const account = await vm.stateManager.getAccount(sender) const balance = GWEI * BigInt(21000) * BigInt(10000000) - account.balance = balance - await vm.stateManager.putAccount(sender, account) + account!.balance = balance + await vm.stateManager.putAccount(sender, account!) let data = '0x60EF60005360016000F3' let res = await runTx(vm, data, 0) @@ -160,10 +162,11 @@ tape('ensure invalid EOF initcode in EIP-3540 does not consume all gas', (t) => eips: [3540], }) const vm = await VM.create({ common }) + await vm.stateManager.putAccount(sender, new Account()) const account = await vm.stateManager.getAccount(sender) const balance = GWEI * BigInt(21000) * BigInt(10000000) - account.balance = balance - await vm.stateManager.putAccount(sender, account) + account!.balance = balance + await vm.stateManager.putAccount(sender, account!) let data = generateEOFCode('60016001F3') const res = await runTx(vm, data, 0) @@ -183,10 +186,11 @@ tape('ensure invalid EOF initcode in EIP-3540 does not consume all gas', (t) => eips: [3540], }) const vm = await VM.create({ common }) + await vm.stateManager.putAccount(sender, new Account()) const account = await vm.stateManager.getAccount(sender) const balance = GWEI * BigInt(21000) * BigInt(10000000) - account.balance = balance - await vm.stateManager.putAccount(sender, account) + account!.balance = balance + await vm.stateManager.putAccount(sender, account!) let data = deployCreateCode(generateEOFCode('60016001F3').substring(2)) const res = await runTx(vm, data, 0) @@ -207,10 +211,11 @@ tape('ensure invalid EOF initcode in EIP-3540 does not consume all gas', (t) => eips: [3540], }) const vm = await VM.create({ common }) + await vm.stateManager.putAccount(sender, new Account()) const account = await vm.stateManager.getAccount(sender) const balance = GWEI * BigInt(21000) * BigInt(10000000) - account.balance = balance - await vm.stateManager.putAccount(sender, account) + account!.balance = balance + await vm.stateManager.putAccount(sender, account!) let data = deployCreate2Code(generateEOFCode('60016001F3').substring(2)) const res = await runTx(vm, data, 0) diff --git a/packages/vm/test/api/EIPs/eip-3651-warm-coinbase.spec.ts b/packages/vm/test/api/EIPs/eip-3651-warm-coinbase.spec.ts index cfb6338094..907ecdb412 100644 --- a/packages/vm/test/api/EIPs/eip-3651-warm-coinbase.spec.ts +++ b/packages/vm/test/api/EIPs/eip-3651-warm-coinbase.spec.ts @@ -1,7 +1,7 @@ import { Block } from '@ethereumjs/block' import { Chain, Common, Hardfork } from '@ethereumjs/common' import { Transaction } from '@ethereumjs/tx' -import { Address, privateToAddress } from '@ethereumjs/util' +import { Account, Address, privateToAddress } from '@ethereumjs/util' import { hexToBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' @@ -33,10 +33,11 @@ const contractAddress = new Address(hexToBytes('ee'.repeat(20))) async function getVM(common: Common) { const vm = await VM.create({ common }) + await vm.stateManager.putAccount(sender, new Account()) const account = await vm.stateManager.getAccount(sender) const balance = GWEI * BigInt(21000) * BigInt(10000000) - account.balance = balance - await vm.stateManager.putAccount(sender, account) + account!.balance = balance + await vm.stateManager.putAccount(sender, account!) await vm.stateManager.putContractCode(contractAddress, code) return vm diff --git a/packages/vm/test/api/EIPs/eip-3670-eof-code-validation.spec.ts b/packages/vm/test/api/EIPs/eip-3670-eof-code-validation.spec.ts index 04ecdb4631..38a3f469d9 100644 --- a/packages/vm/test/api/EIPs/eip-3670-eof-code-validation.spec.ts +++ b/packages/vm/test/api/EIPs/eip-3670-eof-code-validation.spec.ts @@ -1,7 +1,7 @@ import { Chain, Common, Hardfork } from '@ethereumjs/common' import { EOF } from '@ethereumjs/evm/dist/eof' import { FeeMarketEIP1559Transaction } from '@ethereumjs/tx' -import { Address, privateToAddress } from '@ethereumjs/util' +import { Account, Address, privateToAddress } from '@ethereumjs/util' import { hexToBytes, utf8ToBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' @@ -60,10 +60,11 @@ tape('EIP 3670 tests', (t) => { t.test('valid contract code transactions', async (st) => { const vm = await VM.create({ common }) + await vm.stateManager.putAccount(sender, new Account()) const account = await vm.stateManager.getAccount(sender) const balance = GWEI * BigInt(21000) * BigInt(10000000) - account.balance = balance - await vm.stateManager.putAccount(sender, account) + account!.balance = balance + await vm.stateManager.putAccount(sender, account!) let data = '0x67EF0001010001000060005260086018F3' let res = await runTx(vm, data, 0) @@ -76,10 +77,11 @@ tape('EIP 3670 tests', (t) => { t.test('invalid contract code transactions', async (st) => { const vm = await VM.create({ common }) + await vm.stateManager.putAccount(sender, new Account()) const account = await vm.stateManager.getAccount(sender) const balance = GWEI * BigInt(21000) * BigInt(10000000) - account.balance = balance - await vm.stateManager.putAccount(sender, account) + account!.balance = balance + await vm.stateManager.putAccount(sender, account!) const data = '0x67EF0001010001006060005260086018F3' const res = await runTx(vm, data, 0) @@ -138,10 +140,13 @@ tape('EIP 3670 tests', (t) => { const sender = tx.getSenderAddress() + if (i === 0) { + await vm.stateManager.putAccount(sender, new Account()) + } const acc = await vm.stateManager.getAccount(sender) - acc.balance = 1000000000n + acc!.balance = 1000000000n - await vm.stateManager.putAccount(sender, acc) + await vm.stateManager.putAccount(sender, acc!) const ret = await vm.runTx({ tx, skipHardForkValidation: true }) nonce++ diff --git a/packages/vm/test/api/EIPs/eip-3860.spec.ts b/packages/vm/test/api/EIPs/eip-3860.spec.ts index 12d138381b..6231a56a63 100644 --- a/packages/vm/test/api/EIPs/eip-3860.spec.ts +++ b/packages/vm/test/api/EIPs/eip-3860.spec.ts @@ -1,6 +1,6 @@ import { Chain, Common, Hardfork } from '@ethereumjs/common' import { FeeMarketEIP1559Transaction } from '@ethereumjs/tx' -import { Address, privateToAddress } from '@ethereumjs/util' +import { Account, Address, privateToAddress } from '@ethereumjs/util' import { bytesToHex, hexToBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' @@ -18,10 +18,11 @@ tape('EIP 3860 tests', (t) => { t.test('EIP-3860 tests', async (st) => { const vm = await VM.create({ common }) + await vm.stateManager.putAccount(sender, new Account()) const account = await vm.stateManager.getAccount(sender) const balance = GWEI * BigInt(21000) * BigInt(10000000) - account.balance = balance - await vm.stateManager.putAccount(sender, account) + account!.balance = balance + await vm.stateManager.putAccount(sender, account!) const bytes = new Uint8Array(1000000).fill(0x60) const tx = FeeMarketEIP1559Transaction.fromTxData({ diff --git a/packages/vm/test/api/EIPs/eip-4895-withdrawals.spec.ts b/packages/vm/test/api/EIPs/eip-4895-withdrawals.spec.ts index 06ce01077e..71b59db0dc 100644 --- a/packages/vm/test/api/EIPs/eip-4895-withdrawals.spec.ts +++ b/packages/vm/test/api/EIPs/eip-4895-withdrawals.spec.ts @@ -3,7 +3,7 @@ import { Blockchain, parseGethGenesisState } from '@ethereumjs/blockchain' import { Chain, Common, Hardfork } from '@ethereumjs/common' import { decode } from '@ethereumjs/rlp' import { FeeMarketEIP1559Transaction } from '@ethereumjs/tx' -import { Address, GWEI_TO_WEI, KECCAK256_RLP, Withdrawal, zeros } from '@ethereumjs/util' +import { Account, Address, GWEI_TO_WEI, KECCAK256_RLP, Withdrawal, zeros } from '@ethereumjs/util' import { bytesToHex, hexToBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' @@ -62,9 +62,10 @@ tape('EIP4895 tests', (t) => { gasLimit: BigInt(50000), }).sign(pkey) + await vm.stateManager.putAccount(transaction.getSenderAddress(), new Account()) const account = await vm.stateManager.getAccount(transaction.getSenderAddress()) - account.balance = BigInt(1000000) - await vm.stateManager.putAccount(transaction.getSenderAddress(), account) + account!.balance = BigInt(1000000) + await vm.stateManager.putAccount(transaction.getSenderAddress(), account!) let index = 0 for (let i = 0; i < addresses.length; i++) { @@ -104,7 +105,7 @@ tape('EIP4895 tests', (t) => { for (let i = 0; i < addresses.length; i++) { const address = new Address(hexToBytes(addresses[i])) const amount = amounts[i] - const balance = (await vm.stateManager.getAccount(address)).balance + const balance = (await vm.stateManager.getAccount(address))!.balance st.equals(BigInt(amount) * GWEI_TO_WEI, balance, 'balance ok') } diff --git a/packages/vm/test/api/customChain.spec.ts b/packages/vm/test/api/customChain.spec.ts index 3456113b6f..636d958310 100644 --- a/packages/vm/test/api/customChain.spec.ts +++ b/packages/vm/test/api/customChain.spec.ts @@ -86,7 +86,7 @@ tape('VM initialized with custom state', (t) => { const receiverAddress = await vm.stateManager.getAccount(toAddress) t.equal(result.totalGasSpent.toString(), '21000') - t.equal(receiverAddress.balance.toString(), '1') + t.equal(receiverAddress!.balance.toString(), '1') t.end() }) diff --git a/packages/vm/test/api/eei.spec.ts b/packages/vm/test/api/eei.spec.ts index c8cb1184ed..0d5609ed3e 100644 --- a/packages/vm/test/api/eei.spec.ts +++ b/packages/vm/test/api/eei.spec.ts @@ -28,8 +28,8 @@ tape('EEI.copy()', async (t) => { 'copied EEI should have the same hardfork' ) t.equal( - (await copy.getAccount(ZeroAddress)).nonce, - (await eei.getAccount(ZeroAddress)).nonce, + (await copy.getAccount(ZeroAddress))!.nonce, + (await eei.getAccount(ZeroAddress))!.nonce, 'copy should have same State data' ) }) @@ -42,7 +42,7 @@ tape('EEI', (t) => { await Blockchain.create() ) // create a dummy EEI (no VM, no EVM, etc.) st.notOk(await eei.accountExists(ZeroAddress)) - st.ok(await eei.accountIsEmpty(ZeroAddress)) + st.ok(await eei.accountIsEmptyOrNonExistent(ZeroAddress)) st.end() }) @@ -57,12 +57,12 @@ tape('EEI', (t) => { // create empty account await eei.putAccount(ZeroAddress, new Account()) st.ok(await eei.accountExists(ZeroAddress)) - st.ok(await eei.accountIsEmpty(ZeroAddress)) + st.ok(await eei.accountIsEmptyOrNonExistent(ZeroAddress)) // now put a non-empty account const nonEmptyAccount = Account.fromAccountData({ nonce: 1 }) await eei.putAccount(ZeroAddress, nonEmptyAccount) st.ok(await eei.accountExists(ZeroAddress)) - st.notOk(await eei.accountIsEmpty(ZeroAddress)) + st.notOk(await eei.accountIsEmptyOrNonExistent(ZeroAddress)) st.end() } ) @@ -76,10 +76,10 @@ tape('EEI', (t) => { // create empty account await eei.putAccount(ZeroAddress, new Account()) st.ok(await eei.accountExists(ZeroAddress)) // sanity check: account exists before we delete it - st.ok(await eei.accountIsEmpty(ZeroAddress)) // it is obviously empty + st.ok(await eei.accountIsEmptyOrNonExistent(ZeroAddress)) // it is obviously empty await eei.deleteAccount(ZeroAddress) // delete the account st.notOk(await eei.accountExists(ZeroAddress)) // account should not exist - st.ok(await eei.accountIsEmpty(ZeroAddress)) // account is empty + st.ok(await eei.accountIsEmptyOrNonExistent(ZeroAddress)) // account is empty st.end() }) @@ -107,8 +107,8 @@ tape('EEI', (t) => { const accountFromEEI = await vm.eei.getAccount(address) const accountFromEVM = await vm.evm.eei.getAccount(address) st.equal( - accountFromEEI.balance, - accountFromEVM.balance, + accountFromEEI!.balance, + accountFromEVM!.balance, 'vm.eei and evm.eei produce the same accounts' ) }) diff --git a/packages/vm/test/api/runBlock.spec.ts b/packages/vm/test/api/runBlock.spec.ts index b600b015b4..85709e3cc2 100644 --- a/packages/vm/test/api/runBlock.spec.ts +++ b/packages/vm/test/api/runBlock.spec.ts @@ -99,11 +99,9 @@ tape('runBlock() -> successful API parameter usage', async (t) => { skipHardForkValidation: true, }) - const uncleReward = ( - await vm.stateManager.getAccount( - Address.fromString('0xb94f5374fce5ed0000000097c15331677e6ebf0b') - ) - ).balance.toString(16) + const uncleReward = (await vm.stateManager.getAccount( + Address.fromString('0xb94f5374fce5ed0000000097c15331677e6ebf0b') + ))!.balance.toString(16) st.equal( `0x${uncleReward}`, @@ -322,15 +320,15 @@ tape('runBlock() -> runtime behavior', async (t) => { }) const DAOFundedContractAccount1 = await vm.stateManager.getAccount(DAOFundedContractAddress1) - t.equals(DAOFundedContractAccount1.balance, BigInt(0)) // verify our funded account now has 0 balance + t.equals(DAOFundedContractAccount1!.balance, BigInt(0)) // verify our funded account now has 0 balance const DAOFundedContractAccount2 = await vm.stateManager.getAccount(DAOFundedContractAddress2) - t.equals(DAOFundedContractAccount2.balance, BigInt(0)) // verify our funded account now has 0 balance + t.equals(DAOFundedContractAccount2!.balance, BigInt(0)) // verify our funded account now has 0 balance const DAORefundAccount = await vm.stateManager.getAccount(DAORefundAddress) // verify that the refund account gets the summed balance of the original refund account + two child DAO accounts const msg = 'should transfer balance from DAO children to the Refund DAO account in the DAO fork' - t.equal(DAORefundAccount.balance, BigInt(0x7777), msg) + t.equal(DAORefundAccount!.balance, BigInt(0x7777), msg) }) t.test('should allocate to correct clique beneficiary', async (t) => { @@ -368,7 +366,7 @@ tape('runBlock() -> runtime behavior', async (t) => { await vm.runBlock({ block, skipNonce: true, skipBlockValidation: true, generate: true }) const account = await vm.stateManager.getAccount(signer.address) - t.equal(account.balance, BigInt(42000), 'beneficiary balance should equal the cost of the txs') + t.equal(account!.balance, BigInt(42000), 'beneficiary balance should equal the cost of the txs') }) }) diff --git a/packages/vm/test/api/runTx.spec.ts b/packages/vm/test/api/runTx.spec.ts index 0276dc48d9..185fe02210 100644 --- a/packages/vm/test/api/runTx.spec.ts +++ b/packages/vm/test/api/runTx.spec.ts @@ -263,7 +263,7 @@ tape('runTx() -> successful API parameter usage', async (t) => { : result.amountSpent t.equals( - coinbaseAccount.balance, + coinbaseAccount!.balance, expectedCoinbaseBalance, `should use custom block (${txType.name})` ) @@ -377,12 +377,13 @@ tape('runTx() -> API parameter usage/data errors', (t) => { const vm = await VM.create({ common }) const tx = getTransaction(common, 2, true, '0x0', false) const address = tx.getSenderAddress() + await vm.eei.putAccount(address, new Account()) const account = await vm.eei.getAccount(address) - account.balance = BigInt(9000000) // This is the maxFeePerGas multiplied with the gasLimit of 90000 - await vm.eei.putAccount(address, account) + account!.balance = BigInt(9000000) // This is the maxFeePerGas multiplied with the gasLimit of 90000 + await vm.eei.putAccount(address, account!) await vm.runTx({ tx }) - account.balance = BigInt(9000000) - await vm.eei.putAccount(address, account) + account!.balance = BigInt(9000000) + await vm.eei.putAccount(address, account!) const tx2 = getTransaction(common, 2, true, '0x64', false) // Send 100 wei; now balance < maxFeePerGas*gasLimit + callvalue try { await vm.runTx({ tx: tx2 }) @@ -397,10 +398,11 @@ tape('runTx() -> API parameter usage/data errors', (t) => { const vm = await VM.create({ common }) const tx = getTransaction(common, 2, true, '0x0', false) const address = tx.getSenderAddress() + await vm.eei.putAccount(address, new Account()) const account = await vm.eei.getAccount(address) - account.balance = BigInt(9000000) // This is the maxFeePerGas multiplied with the gasLimit of 90000 - account.nonce = BigInt(1) - await vm.eei.putAccount(address, account) + account!.balance = BigInt(9000000) // This is the maxFeePerGas multiplied with the gasLimit of 90000 + account!.nonce = BigInt(1) + await vm.eei.putAccount(address, account!) try { await vm.runTx({ tx }) t.fail('cannot reach this') @@ -651,15 +653,16 @@ tape('runTx() -> consensus bugs', async (t) => { const vm = await VM.create({ common }) const addr = Address.fromString('0xd3563d8f19a85c95beab50901fd59ca4de69174c') + await vm.eei.putAccount(addr, new Account()) const acc = await vm.eei.getAccount(addr) - acc.balance = beforeBalance - acc.nonce = BigInt(2) - await vm.eei.putAccount(addr, acc) + acc!.balance = beforeBalance + acc!.nonce = BigInt(2) + await vm.eei.putAccount(addr, acc!) const tx = Transaction.fromTxData(txData, { common }) await vm.runTx({ tx }) - const newBalance = (await vm.eei.getAccount(addr)).balance + const newBalance = (await vm.eei.getAccount(addr))!.balance t.equals(newBalance, afterBalance) t.end() }) @@ -689,9 +692,10 @@ tape('runTx() -> consensus bugs', async (t) => { const vm = await VM.create({ common }) const addr = Address.fromPrivateKey(pkey) + await vm.eei.putAccount(addr, new Account()) const acc = await vm.eei.getAccount(addr) - acc.balance = BigInt(10000000000000) - await vm.eei.putAccount(addr, acc) + acc!.balance = BigInt(10000000000000) + await vm.eei.putAccount(addr, acc!) const tx = FeeMarketEIP1559Transaction.fromTxData(txData, { common }).sign(pkey) @@ -755,7 +759,7 @@ tape('runTx() -> skipBalance behavior', async (t) => { const res = await vm.runTx({ tx, skipBalance: true, skipHardForkValidation: true }) t.pass('runTx should not throw with no balance and skipBalance') - const afterTxBalance = (await vm.stateManager.getAccount(sender)).balance + const afterTxBalance = (await vm.stateManager.getAccount(sender))!.balance t.equal( afterTxBalance, balance !== undefined ? balance - 1n : BigInt(0), @@ -786,9 +790,10 @@ tape( }).sign(pkey) const addr = Address.fromPrivateKey(pkey) + await vm.eei.putAccount(addr, new Account()) const acc = await vm.eei.getAccount(addr) - acc.balance = BigInt(tx.gasLimit * tx.gasPrice) - await vm.eei.putAccount(addr, acc) + acc!.balance = BigInt(tx.gasLimit * tx.gasPrice) + await vm.eei.putAccount(addr, acc!) await vm.runTx({ tx, skipHardForkValidation: true }) const hash = await vm.stateManager.getContractStorage(codeAddr, hexToBytes('00'.repeat(32))) @@ -824,9 +829,10 @@ tape( }).sign(pkey) const addr = Address.fromPrivateKey(pkey) + await vm.eei.putAccount(addr, new Account()) const acc = await vm.eei.getAccount(addr) - acc.balance = BigInt(tx.gasLimit * tx.gasPrice + tx.value) - await vm.eei.putAccount(addr, acc) + acc!.balance = BigInt(tx.gasLimit * tx.gasPrice + tx.value) + await vm.eei.putAccount(addr, acc!) t.equals( (await vm.runTx({ tx, skipHardForkValidation: true })).totalGasSpent, BigInt(27818), @@ -859,9 +865,10 @@ tape( }).sign(pkey) const addr = Address.fromPrivateKey(pkey) + await vm.eei.putAccount(addr, new Account()) const acc = await vm.eei.getAccount(addr) - acc.balance = BigInt(tx.gasLimit * tx.gasPrice + tx.value) - await vm.eei.putAccount(addr, acc) + acc!.balance = BigInt(tx.gasLimit * tx.gasPrice + tx.value) + await vm.eei.putAccount(addr, acc!) t.equals( (await vm.runTx({ tx, skipHardForkValidation: true })).totalGasSpent, BigInt(13001), diff --git a/packages/vm/test/api/state/accountExists.spec.ts b/packages/vm/test/api/state/accountExists.spec.ts index 9cfa94447a..8c349f7522 100644 --- a/packages/vm/test/api/state/accountExists.spec.ts +++ b/packages/vm/test/api/state/accountExists.spec.ts @@ -1,5 +1,5 @@ import { Chain, Common, Hardfork } from '@ethereumjs/common' -import { Address, toBytes } from '@ethereumjs/util' +import { Account, Address, toBytes } from '@ethereumjs/util' import { hexToBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' @@ -20,9 +20,10 @@ tape('correctly apply new account gas fee on pre-Spurious Dragon hardforks', asy '606060405236156101065760e060020a600035046305fefda7811461013d57806306fdde031461016357806318160ddd146101c057806323b872dd146101c95780632e1a7d4d146101fb578063313ce5671461021e5780633177029f1461022a57806347f1d8d7146102d25780634b750334146102db57806370a08231146102e45780638620410b146102fc5780638da5cb5b1461030557806395d89b4114610317578063a6f2ae3a14610372578063a9059cbb146103a2578063b414d4b6146103d1578063c91d956c146103ec578063dc3080f21461040f578063dd62ed3e14610434578063e4849b3214610459578063e724529c1461048f578063f2fde38b146104b5575b6104d860055434111561013b5760055433600160a060020a031660009081526008602052604090208054349290920490910190555b565b6104d8600435602435600054600160a060020a0390811633919091161461084157610002565b60408051600180546020600282841615610100026000190190921691909104601f81018290048202840182019094528383526104da93908301828280156105db5780601f106105b0576101008083540402835291602001916105db565b61054860065481565b610548600435602435604435600160a060020a038316600090815260086020526040812054829010156106f657610002565b6104d8600435600054600160a060020a0390811633919091161461091957610002565b61055a60035460ff1681565b610548600435602435600160a060020a033381166000818152600a60209081526040808320878616808552925280832086905580517f4889ca880000000000000000000000000000000000000000000000000000000081526004810194909452602484018690523090941660448401529251909285929091634889ca88916064808201928792909190829003018183876161da5a03f115610002575060019695505050505050565b61054860075481565b61054860045481565b61054860043560086020526000908152604090205481565b61054860055481565b610571600054600160a060020a031681565b6040805160028054602060018216156101000260001901909116829004601f81018290048202840182019094528383526104da93908301828280156105db5780601f106105b0576101008083540402835291602001916105db565b60055430600160a060020a03166000908152600860205260409020546104d8913404908190101561084c57610002565b6104d8600435602435600160a060020a033316600090815260086020526040902054819010156105f157610002565b61054860043560096020526000908152604090205460ff1681565b6104d8600435600054600160a060020a039081163391909116146105e357610002565b600b602090815260043560009081526040808220909252602435815220546105489081565b600a602090815260043560009081526040808220909252602435815220546105489081565b6104d86004355b806008600050600033600160a060020a031681526020019081526020016000206000505410156108a657610002565b6104d8600435602435600054600160a060020a039081163391909116146107e157610002565b6104d8600435600054600160a060020a0390811633919091161461058e57610002565b005b60405180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f16801561053a5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b60408051918252519081900360200190f35b6040805160ff929092168252519081900360200190f35b60408051600160a060020a03929092168252519081900360200190f35b6000805473ffffffffffffffffffffffffffffffffffffffff19168217905550565b820191906000526020600020905b8154815290600101906020018083116105be57829003601f168201915b505050505081565b66038d7ea4c6800002600755565b600160a060020a038216600090815260086020526040902054818101101561061857610002565b600160a060020a03331660009081526009602052604090205460ff161561063e57610002565b600160a060020a0333811660008181526008602090815260408083208054879003905593861680835291849020805486019055835185815293519193600080516020610940833981519152929081900390910190a3600754600160a060020a0383163110156106c4576007546004546106c491600160a060020a03851631900304610460565b604051600454600754600160a060020a038516926000928431909203919091049082818181858883f150505050505050565b600160a060020a038316600090815260086020526040902054808301101561071d57610002565b600160a060020a038481166000818152600a602090815260408083203390951680845294825280832054938352600b825280832094835293905291909120548301111561076957610002565b600160a060020a03848116600081815260086020908152604080832080548890039055878516808452818420805489019055848452600b835281842033909616845294825291829020805487019055815186815291516000805160206109408339815191529281900390910190a35060019392505050565b600160a060020a038216600081815260096020908152604091829020805460ff1916851790558151928352820183905280517f48335238b4855f35377ed80f164e8c6f3c366e54ac00b96a6402d4a9814a03a59281900390910190a15050565b600491909155600555565b600160a060020a03338116600081815260086020908152604080832080548701905530909416808352918490208054869003905583518581529351929391926000805160206109408339815191529281900390910190a350565b30600160a060020a039081166000908152600860205260408082208054850190553390921680825282822080548590039055915160045484029082818181858883f15084815260405130600160a060020a031694935060008051602061094083398151915292509081900360200190a350565b60008054604051600160a060020a03919091169190839082818181858883f150505050505056ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef' const existingAddress = caller + await vm.stateManager.putAccount(existingAddress, new Account()) const existingAccount = await vm.stateManager.getAccount(existingAddress) - existingAccount.balance = BigInt(1) - await vm.stateManager.putAccount(existingAddress, existingAccount) + existingAccount!.balance = BigInt(1) + await vm.stateManager.putAccount(existingAddress, existingAccount!) await vm.stateManager.putContractCode(contractAddress, hexToBytes(code)) // setup the contract code await vm.stateManager.putContractStorage( contractAddress, @@ -61,11 +62,13 @@ tape( const code = '606060405236156101065760e060020a600035046305fefda7811461013d57806306fdde031461016357806318160ddd146101c057806323b872dd146101c95780632e1a7d4d146101fb578063313ce5671461021e5780633177029f1461022a57806347f1d8d7146102d25780634b750334146102db57806370a08231146102e45780638620410b146102fc5780638da5cb5b1461030557806395d89b4114610317578063a6f2ae3a14610372578063a9059cbb146103a2578063b414d4b6146103d1578063c91d956c146103ec578063dc3080f21461040f578063dd62ed3e14610434578063e4849b3214610459578063e724529c1461048f578063f2fde38b146104b5575b6104d860055434111561013b5760055433600160a060020a031660009081526008602052604090208054349290920490910190555b565b6104d8600435602435600054600160a060020a0390811633919091161461084157610002565b60408051600180546020600282841615610100026000190190921691909104601f81018290048202840182019094528383526104da93908301828280156105db5780601f106105b0576101008083540402835291602001916105db565b61054860065481565b610548600435602435604435600160a060020a038316600090815260086020526040812054829010156106f657610002565b6104d8600435600054600160a060020a0390811633919091161461091957610002565b61055a60035460ff1681565b610548600435602435600160a060020a033381166000818152600a60209081526040808320878616808552925280832086905580517f4889ca880000000000000000000000000000000000000000000000000000000081526004810194909452602484018690523090941660448401529251909285929091634889ca88916064808201928792909190829003018183876161da5a03f115610002575060019695505050505050565b61054860075481565b61054860045481565b61054860043560086020526000908152604090205481565b61054860055481565b610571600054600160a060020a031681565b6040805160028054602060018216156101000260001901909116829004601f81018290048202840182019094528383526104da93908301828280156105db5780601f106105b0576101008083540402835291602001916105db565b60055430600160a060020a03166000908152600860205260409020546104d8913404908190101561084c57610002565b6104d8600435602435600160a060020a033316600090815260086020526040902054819010156105f157610002565b61054860043560096020526000908152604090205460ff1681565b6104d8600435600054600160a060020a039081163391909116146105e357610002565b600b602090815260043560009081526040808220909252602435815220546105489081565b600a602090815260043560009081526040808220909252602435815220546105489081565b6104d86004355b806008600050600033600160a060020a031681526020019081526020016000206000505410156108a657610002565b6104d8600435602435600054600160a060020a039081163391909116146107e157610002565b6104d8600435600054600160a060020a0390811633919091161461058e57610002565b005b60405180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f16801561053a5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b60408051918252519081900360200190f35b6040805160ff929092168252519081900360200190f35b60408051600160a060020a03929092168252519081900360200190f35b6000805473ffffffffffffffffffffffffffffffffffffffff19168217905550565b820191906000526020600020905b8154815290600101906020018083116105be57829003601f168201915b505050505081565b66038d7ea4c6800002600755565b600160a060020a038216600090815260086020526040902054818101101561061857610002565b600160a060020a03331660009081526009602052604090205460ff161561063e57610002565b600160a060020a0333811660008181526008602090815260408083208054879003905593861680835291849020805486019055835185815293519193600080516020610940833981519152929081900390910190a3600754600160a060020a0383163110156106c4576007546004546106c491600160a060020a03851631900304610460565b604051600454600754600160a060020a038516926000928431909203919091049082818181858883f150505050505050565b600160a060020a038316600090815260086020526040902054808301101561071d57610002565b600160a060020a038481166000818152600a602090815260408083203390951680845294825280832054938352600b825280832094835293905291909120548301111561076957610002565b600160a060020a03848116600081815260086020908152604080832080548890039055878516808452818420805489019055848452600b835281842033909616845294825291829020805487019055815186815291516000805160206109408339815191529281900390910190a35060019392505050565b600160a060020a038216600081815260096020908152604091829020805460ff1916851790558151928352820183905280517f48335238b4855f35377ed80f164e8c6f3c366e54ac00b96a6402d4a9814a03a59281900390910190a15050565b600491909155600555565b600160a060020a03338116600081815260086020908152604080832080548701905530909416808352918490208054869003905583518581529351929391926000805160206109408339815191529281900390910190a350565b30600160a060020a039081166000908152600860205260408082208054850190553390921680825282822080548590039055915160045484029082818181858883f15084815260405130600160a060020a031694935060008051602061094083398151915292509081900360200190a350565b60008054604051600160a060020a03919091169190839082818181858883f150505050505056ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef' const existingAddress = caller + await vm.stateManager.putAccount(existingAddress, new Account()) const existingAccount = await vm.stateManager.getAccount(existingAddress) - existingAccount.balance = BigInt(1) - await vm.stateManager.putAccount(existingAddress, existingAccount) + existingAccount!.balance = BigInt(1) + await vm.stateManager.putAccount(existingAddress, existingAccount!) // add empty account to DB const emptyAddress = new Address(hexToBytes('f48a1bdc65d9ccb4b569ffd4bffff415b90783d6')) + await vm.stateManager.putAccount(emptyAddress, new Account()) const emptyAccount = await vm.stateManager.getAccount(emptyAddress) //@ts-ignore vm.stateManager._trie.put(toBytes(emptyAddress), emptyAccount.serialize()) diff --git a/packages/vm/test/tester/runners/BlockchainTestsRunner.ts b/packages/vm/test/tester/runners/BlockchainTestsRunner.ts index 4dc1cc65ce..508e87937f 100644 --- a/packages/vm/test/tester/runners/BlockchainTestsRunner.ts +++ b/packages/vm/test/tester/runners/BlockchainTestsRunner.ts @@ -2,6 +2,7 @@ import { Block } from '@ethereumjs/block' import { Blockchain } from '@ethereumjs/blockchain' import { ConsensusAlgorithm, Hardfork } from '@ethereumjs/common' import { RLP } from '@ethereumjs/rlp' +import { DefaultStateManager } from '@ethereumjs/statemanager' import { Trie } from '@ethereumjs/trie' import { TransactionFactory } from '@ethereumjs/tx' import { bytesToBigInt, isHexPrefixed, stripHexPrefix, toBytes } from '@ethereumjs/util' @@ -40,10 +41,13 @@ export async function runBlockchainTest(options: any, testData: any, t: tape.Tes // fix for BlockchainTests/GeneralStateTests/stRandom/* testData.lastblockhash = stripHexPrefix(testData.lastblockhash) - const cacheDB = new Level('./.cachedb') - const state = new Trie({ useKeyHashing: true }) + let cacheDB = new Level('./.cachedb') + let state = new Trie({ useKeyHashing: true }) + let stateManager = new DefaultStateManager({ + trie: state, + }) - const { common }: { common: Common } = options + let common = options.common.copy() as Common common.setHardforkByBlockNumber(0) let validatePow = false @@ -67,7 +71,7 @@ export async function runBlockchainTest(options: any, testData: any, t: tape.Tes t.deepEquals(genesisBlock.serialize(), rlp, 'correct genesis RLP') } - const blockchain = await Blockchain.create({ + let blockchain = await Blockchain.create({ db: new MemoryLevel(), common, validateBlocks: true, @@ -88,8 +92,8 @@ export async function runBlockchainTest(options: any, testData: any, t: tape.Tes const begin = Date.now() - const vm = await VM.create({ - state, + let vm = await VM.create({ + stateManager, blockchain, common, hardforkByBlockNumber: true, @@ -239,4 +243,7 @@ export async function runBlockchainTest(options: any, testData: any, t: tape.Tes const timeSpent = `${(end - begin) / 1000} secs` t.comment(`Time: ${timeSpent}`) await cacheDB.close() + + // @ts-ignore Explicitly delete objects for memory optimization (early GC) + common = blockchain = state = stateManager = vm = cacheDB = null // eslint-disable-line } diff --git a/packages/vm/test/tester/runners/GeneralStateTestsRunner.ts b/packages/vm/test/tester/runners/GeneralStateTestsRunner.ts index 00ba0b97f0..91dab4ce31 100644 --- a/packages/vm/test/tester/runners/GeneralStateTestsRunner.ts +++ b/packages/vm/test/tester/runners/GeneralStateTestsRunner.ts @@ -74,19 +74,21 @@ async function runTestCase(options: any, testData: any, t: tape.Test) { ;({ VM } = require('../../../src')) } const begin = Date.now() - const common = options.common + // Copy the common object to not create long-lasting + // references in memory which might prevent GC + let common = options.common.copy() // Have to create a blockchain with empty block as genesisBlock for Merge // Otherwise mainnet genesis will throw since this has difficulty nonzero const genesisBlock = new Block(undefined, undefined, undefined, { common }) - const blockchain = await Blockchain.create({ genesisBlock, common }) - const state = new Trie({ useKeyHashing: true }) - const stateManager = new DefaultStateManager({ + let blockchain = await Blockchain.create({ genesisBlock, common }) + let state = new Trie({ useKeyHashing: true }) + let stateManager = new DefaultStateManager({ trie: state, }) - const eei = new EEI(stateManager, common, blockchain) - const evm = new EVM({ common, eei }) - const vm = await VM.create({ state, stateManager, common, blockchain, evm }) + let eei = new EEI(stateManager, common, blockchain) + let evm = new EVM({ common, eei }) + let vm = await VM.create({ state, stateManager, common, blockchain, evm }) await setupPreConditions(vm.eei, testData) @@ -102,37 +104,41 @@ async function runTestCase(options: any, testData: any, t: tape.Test) { // Even if no txs are ran, coinbase should always be created const coinbaseAddress = Address.fromString(testData.env.currentCoinbase) const account = await (vm).eei.getAccount(coinbaseAddress) - await (vm).eei.putAccount(coinbaseAddress, account) + await (vm).eei.putAccount(coinbaseAddress, account!) + + const stepHandler = (e: InterpreterStep) => { + let hexStack = [] + hexStack = e.stack.map((item: bigint) => { + return '0x' + item.toString(16) + }) + + const opTrace = { + pc: e.pc, + op: e.opcode.name, + gas: '0x' + e.gasLeft.toString(16), + gasCost: '0x' + e.opcode.fee.toString(16), + stack: hexStack, + depth: e.depth, + opName: e.opcode.name, + } + + t.comment(JSON.stringify(opTrace)) + } + + const afterTxHandler = async () => { + const stateRoot = { + stateRoot: bytesToHex(vm.stateManager._trie.root), + } + t.comment(JSON.stringify(stateRoot)) + } if (tx) { if (tx.validate()) { const block = makeBlockFromEnv(testData.env, { common }) if (options.jsontrace === true) { - vm.evm.events.on('step', function (e: InterpreterStep) { - let hexStack = [] - hexStack = e.stack.map((item: bigint) => { - return '0x' + item.toString(16) - }) - - const opTrace = { - pc: e.pc, - op: e.opcode.name, - gas: '0x' + e.gasLeft.toString(16), - gasCost: '0x' + e.opcode.fee.toString(16), - stack: hexStack, - depth: e.depth, - opName: e.opcode.name, - } - - t.comment(JSON.stringify(opTrace)) - }) - vm.events.on('afterTx', async () => { - const stateRoot = { - stateRoot: bytesToHex(vm.stateManager._trie.root), - } - t.comment(JSON.stringify(stateRoot)) - }) + vm.evm.events.on('step', stepHandler) + vm.events.on('afterTx', afterTxHandler) } try { await vm.runTx({ tx, block }) @@ -157,6 +163,13 @@ async function runTestCase(options: any, testData: any, t: tape.Test) { const timeSpent = `${(end - begin) / 1000} secs` t.ok(stateRootsAreEqual, `[ ${timeSpent} ] the state roots should match (${execInfo})`) + + vm.evm.events.removeListener('step', stepHandler) + vm.events.removeListener('afterTx', afterTxHandler) + + // @ts-ignore Explicitly delete objects for memory optimization (early GC) + common = blockchain = state = stateManager = eei = evm = vm = null // eslint-disable-line + return parseFloat(timeSpent) } diff --git a/packages/vm/test/util.ts b/packages/vm/test/util.ts index f6e1978661..426df08850 100644 --- a/packages/vm/test/util.ts +++ b/packages/vm/test/util.ts @@ -335,6 +335,7 @@ export async function setupPreConditions(state: VmState, testData: any) { const addressBuf = format(addressStr) const address = new Address(addressBuf) + await state.putAccount(address, new Account()) const codeBuf = format(code) const codeHash = keccak256(codeBuf) @@ -352,7 +353,7 @@ export async function setupPreConditions(state: VmState, testData: any) { // Put contract code await state.putContractCode(address, codeBuf) - const storageRoot = (await state.getAccount(address)).storageRoot + const storageRoot = (await state.getAccount(address))!.storageRoot if (testData.exec?.address === addressStr) { testData.root(storageRoot) From 30aaa9a3e7f41d1b9fe91e543d7418f2365f2246 Mon Sep 17 00:00:00 2001 From: harkamal Date: Wed, 12 Apr 2023 17:22:49 +0530 Subject: [PATCH 07/53] Rebase on master commit: 205dc35 and cleanup buffer references fix karma config --- .../client/lib/sync/fetcher/accountfetcher.ts | 7 +-- .../lib/sync/fetcher/bytecodefetcher.ts | 51 ++++++++++--------- .../test/sync/fetcher/bytecodefetcher.spec.ts | 33 ++++++------ packages/tx/karma.conf.js | 1 + 4 files changed, 47 insertions(+), 45 deletions(-) diff --git a/packages/client/lib/sync/fetcher/accountfetcher.ts b/packages/client/lib/sync/fetcher/accountfetcher.ts index eb680b38af..42112fe865 100644 --- a/packages/client/lib/sync/fetcher/accountfetcher.ts +++ b/packages/client/lib/sync/fetcher/accountfetcher.ts @@ -88,10 +88,7 @@ export function snapFetchersCompleted( fetcherDoneFlags.storageFetcherDone && fetcherDoneFlags.byteCodeFetcherDone ) { - fetcherDoneFlags.eventBus!.emit( - Event.SYNC_SNAPSYNC_COMPLETE, - bufArrToArr(fetcherDoneFlags.stateRoot!) - ) + fetcherDoneFlags.eventBus!.emit(Event.SYNC_SNAPSYNC_COMPLETE, fetcherDoneFlags.stateRoot!) } } @@ -360,7 +357,7 @@ export class AccountFetcher extends Fetcher const storageRoot: Uint8Array = account.body[2] instanceof Uint8Array ? account.body[2] : Uint8Array.from(account.body[2]) if (!equalsBytes(storageRoot, KECCAK256_RLP)) { - storageFetchRequests.push({ + storageFetchRequests.add({ accountHash: account.hash, storageRoot, first: BigInt(0), diff --git a/packages/client/lib/sync/fetcher/bytecodefetcher.ts b/packages/client/lib/sync/fetcher/bytecodefetcher.ts index fbe65750ac..cf7dc907ed 100644 --- a/packages/client/lib/sync/fetcher/bytecodefetcher.ts +++ b/packages/client/lib/sync/fetcher/bytecodefetcher.ts @@ -1,6 +1,6 @@ import { CODEHASH_PREFIX } from '@ethereumjs/statemanager' import { Trie } from '@ethereumjs/trie' -import { bufferToHex } from '@ethereumjs/util' +import { bytesToHex, concatBytes, equalsBytes } from '@ethereumjs/util' import { debug as createDebugLogger } from 'debug' import { keccak256 } from 'ethereum-cryptography/keccak' @@ -12,14 +12,14 @@ import type { Job } from './types' import type { BatchDBOp } from '@ethereumjs/trie' import type { Debugger } from 'debug' -type ByteCodeDataResponse = Buffer[] & { completed?: boolean } +type ByteCodeDataResponse = Uint8Array[] & { completed?: boolean } /** * Implements an snap1 based bytecode fetcher * @memberof module:sync/fetcher */ export interface ByteCodeFetcherOptions extends FetcherOptions { - hashes: Buffer[] + hashes: Uint8Array[] trie: Trie /** Destroy fetcher once all tasks are done */ @@ -28,13 +28,13 @@ export interface ByteCodeFetcherOptions extends FetcherOptions { // root comes from block? export type JobTask = { - hashes: Buffer[] + hashes: Uint8Array[] } -export class ByteCodeFetcher extends Fetcher { +export class ByteCodeFetcher extends Fetcher { protected debug: Debugger - hashes: Buffer[] + hashes: Uint8Array[] trie: Trie @@ -47,7 +47,7 @@ export class ByteCodeFetcher extends Fetcher { this.trie = options.trie ?? new Trie({ useKeyHashing: false }) this.debug = createDebugLogger('client:ByteCodeFetcher') if (this.hashes.length > 0) { - const fullJob = { task: { hashes: this.hashes } } as Job + const fullJob = { task: { hashes: this.hashes } } as Job this.debug( `Bytecode fetcher instantiated ${fullJob.task.hashes.length} hash requests destroyWhenDone=${this.destroyWhenDone}` ) @@ -65,10 +65,12 @@ export class ByteCodeFetcher extends Fetcher { * @param job * @param peer */ - async request(job: Job): Promise { + async request( + job: Job + ): Promise { const { task, peer } = job - this.debug(`requested code hashes: ${Array.from(task.hashes).map((h) => bufferToHex(h))}`) + this.debug(`requested code hashes: ${Array.from(task.hashes).map((h) => bytesToHex(h))}`) const rangeResult = await peer!.snap!.getByteCodes({ hashes: Array.from(task.hashes), @@ -85,8 +87,8 @@ export class ByteCodeFetcher extends Fetcher { // Cross reference the requested bytecodes with the response to find gaps // that the serving node is missing - const receivedCodes: Map = new Map() - const missingCodeHashes: Buffer[] = [] + const receivedCodes: Map = new Map() + const missingCodeHashes: Uint8Array[] = [] // While results are in the same order as requested hashes but there could be gaps/misses in the results // if the node doesn't has the bytecode. We need an index to move forward through the hashes which are @@ -94,12 +96,12 @@ export class ByteCodeFetcher extends Fetcher { let requestedHashIndex = 0 for (let i = 0; i < rangeResult.codes.length; i++) { const receivedCode = rangeResult.codes[i] - const receivedHash = Buffer.from(keccak256(receivedCode)) + const receivedHash = keccak256(receivedCode) // move forward requestedHashIndex till the match has been found while ( requestedHashIndex < task.hashes.length && - receivedHash.compare(task.hashes[requestedHashIndex]) !== 0 + !equalsBytes(receivedHash, task.hashes[requestedHashIndex]) ) { // requestedHashIndex 's hash is skipped in response missingCodeHashes.push(task.hashes[requestedHashIndex]) @@ -111,7 +113,7 @@ export class ByteCodeFetcher extends Fetcher { break } else { // match found - receivedCodes.set(bufferToHex(receivedHash), receivedCode) + receivedCodes.set(bytesToHex(receivedHash), receivedCode) } } @@ -130,7 +132,10 @@ export class ByteCodeFetcher extends Fetcher { * @param job fetch job * @param result result data */ - process(job: Job, result: ByteCodeDataResponse): Buffer[] | undefined { + process( + job: Job, + result: ByteCodeDataResponse + ): Uint8Array[] | undefined { const fullResult = (job.partialResult ?? []).concat(result) job.partialResult = undefined if (result.completed === true) { @@ -145,13 +150,13 @@ export class ByteCodeFetcher extends Fetcher { * Store fetch result. Resolves once store operation is complete. * @param result fetch result */ - async store(result: Buffer[]): Promise { - const codeHashToByteCode = result[0] as unknown as Map + async store(result: Uint8Array[]): Promise { + const codeHashToByteCode = result[0] as unknown as Map const ops = [] let storeCount = 0 for (const [_, value] of codeHashToByteCode) { - const codeHash = Buffer.from(keccak256(value)) - const computedKey = Buffer.concat([CODEHASH_PREFIX, codeHash]) + const codeHash = keccak256(value) + const computedKey = concatBytes(CODEHASH_PREFIX, codeHash) ops.push({ type: 'put', key: computedKey, @@ -175,7 +180,7 @@ export class ByteCodeFetcher extends Fetcher { * @param numberList List of block numbers * @param min Start block number */ - enqueueByByteCodeRequestList(byteCodeRequestList: Buffer[]) { + enqueueByByteCodeRequestList(byteCodeRequestList: Uint8Array[]) { this.hashes.push(...byteCodeRequestList) this.debug( `Number of bytecode fetch requests added to fetcher queue: ${byteCodeRequestList.length}` @@ -201,12 +206,12 @@ export class ByteCodeFetcher extends Fetcher { this.debug(`Entering nextTasks with hash request queue length of ${this.hashes.length}`) this.debug('Bytecode requests in primary queue:') for (const h of this.hashes) { - this.debug(`\tCode hash: ${bufferToHex(h)}`) + this.debug(`\tCode hash: ${bytesToHex(h)}`) this.debug('\t---') } try { if (this.in.length === 0 && this.hashes.length > 0) { - const fullJob = { task: { hashes: this.hashes } } as Job + const fullJob = { task: { hashes: this.hashes } } as Job const tasks = this.tasks() for (const task of tasks) { this.enqueueTask(task, true) @@ -251,7 +256,7 @@ export class ByteCodeFetcher extends Fetcher { * @param job * @param withIndex pass true to additionally output job.index */ - jobStr(job: Job, withIndex = false) { + jobStr(job: Job, withIndex = false) { let str = '' if (withIndex) { str += `index=${job.index} ` diff --git a/packages/client/test/sync/fetcher/bytecodefetcher.spec.ts b/packages/client/test/sync/fetcher/bytecodefetcher.spec.ts index 0b351cf64f..68efcdd005 100644 --- a/packages/client/test/sync/fetcher/bytecodefetcher.spec.ts +++ b/packages/client/test/sync/fetcher/bytecodefetcher.spec.ts @@ -1,5 +1,6 @@ import { RLP } from '@ethereumjs/rlp' import { Trie } from '@ethereumjs/trie' +import { hexToBytes, utf8ToBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' import * as td from 'testdouble' @@ -30,16 +31,14 @@ tape('[ByteCodeFetcher]', async (t) => { config, pool, trie: new Trie({ useKeyHashing: false }), - hashes: [ - Buffer.from('2034f79e0e33b0ae6bef948532021baceb116adf2616478703bec6b17329f1cc', 'hex'), - ], + hashes: [hexToBytes('2034f79e0e33b0ae6bef948532021baceb116adf2616478703bec6b17329f1cc')], }) fetcher.next = () => false t.notOk((fetcher as any).running, 'not started') t.equals((fetcher as any).in.length, 0, 'No jobs have yet been added') t.equal((fetcher as any).hashes.length, 1, 'one codehash have been added') fetcher.enqueueByByteCodeRequestList([ - Buffer.from('2034f79e0e33b0ae6bef948532021baceb116adf2616478703bec6b17329f1cc', 'hex'), + hexToBytes('2034f79e0e33b0ae6bef948532021baceb116adf2616478703bec6b17329f1cc'), ]) t.equals((fetcher as any).in.length, 1, 'A new task has been queued') const job = (fetcher as any).in.peek() @@ -65,12 +64,12 @@ tape('[ByteCodeFetcher]', async (t) => { hashes: [], }) - const fullResult: any = [Buffer.from('')] + const fullResult: any = [utf8ToBytes('')] - const ByteCodeResponse: any = [Buffer.from('')] + const ByteCodeResponse: any = [utf8ToBytes('')] ByteCodeResponse.completed = true const task = { - hashes: [Buffer.from('')], + hashes: [utf8ToBytes('')], } ;(fetcher as any).running = true fetcher.enqueueTask(task) @@ -89,10 +88,10 @@ tape('[ByteCodeFetcher]', async (t) => { trie: new Trie({ useKeyHashing: false }), hashes: [], }) - const ByteCodeResponse: any = [Buffer.from(''), Buffer.from('')] + const ByteCodeResponse: any = [utf8ToBytes(''), utf8ToBytes('')] ByteCodeResponse.completed = false const task = { - hashes: [Buffer.from('')], + hashes: [utf8ToBytes('')], } ;(fetcher as any).running = true fetcher.enqueueTask(task) @@ -101,7 +100,7 @@ tape('[ByteCodeFetcher]', async (t) => { t.equal((fetcher as any).in.length, 1, 'Fetcher should still have same job') t.equal(job?.partialResult.length, 2, 'Should have two partial results') t.equal(results, undefined, 'Process should not return full results yet') - const remainingBytesCodeData: any = [Buffer.from(''), Buffer.from(''), Buffer.from('')] + const remainingBytesCodeData: any = [utf8ToBytes(''), utf8ToBytes(''), utf8ToBytes('')] remainingBytesCodeData.completed = true results = fetcher.process(job as any, remainingBytesCodeData) t.equal((results as any).length, 5, 'Should return full results') @@ -122,14 +121,14 @@ tape('[ByteCodeFetcher]', async (t) => { const task = { hashes: [ - Buffer.from('28ec5c6e71bc4243030bc6aa069616b4497c150c883c019dee059279f0593cd8', 'hex'), - Buffer.from('418df730969850c4f5c10d09ca929d018ee4c5d71243aa7440560e2265c37aab', 'hex'), - Buffer.from('01b45b4d94f26e3f7a84ea31f7338c0f621d3f3ee38e439611a0954da7e2d728', 'hex'), - Buffer.from('6bd103c66d7d0908a75ae23d5f6de62865be2784408cf07906eaffe515616212', 'hex'), - Buffer.from('0c9d7b40fa7bb308c9b029f7b2840bc1071760c55cdf136b08f0f81ace379399', 'hex'), + hexToBytes('28ec5c6e71bc4243030bc6aa069616b4497c150c883c019dee059279f0593cd8'), + hexToBytes('418df730969850c4f5c10d09ca929d018ee4c5d71243aa7440560e2265c37aab'), + hexToBytes('01b45b4d94f26e3f7a84ea31f7338c0f621d3f3ee38e439611a0954da7e2d728'), + hexToBytes('6bd103c66d7d0908a75ae23d5f6de62865be2784408cf07906eaffe515616212'), + hexToBytes('0c9d7b40fa7bb308c9b029f7b2840bc1071760c55cdf136b08f0f81ace379399'), ], } - const resData = RLP.decode(Buffer.from(_byteCodesRLP, 'hex')) as unknown + const resData = RLP.decode(hexToBytes(_byteCodesRLP)) as unknown const res = p.decode(p.messages.filter((message) => message.name === 'ByteCodes')[0], resData) const { reqId, codes } = res const mockedGetByteCodes = td.func() @@ -170,7 +169,7 @@ tape('[ByteCodeFetcher]', async (t) => { config, pool, trie: new Trie({ useKeyHashing: false }), - hashes: [Buffer.from('')], + hashes: [utf8ToBytes('')], }) td.when((fetcher as any).pool.idle(td.matchers.anything())).thenReturn('peer0') t.equals(fetcher.peer(), 'peer0', 'found peer') diff --git a/packages/tx/karma.conf.js b/packages/tx/karma.conf.js index 0a32a4208d..01e70794c7 100644 --- a/packages/tx/karma.conf.js +++ b/packages/tx/karma.conf.js @@ -15,6 +15,7 @@ module.exports = function (config) { acornOptions: { ecmaVersion: 12, }, + ignore: ['c-kzg', 'safer-buffer'], resolve: { alias: { '@chainsafe/persistent-merkle-tree/hasher': From 2bd9854e128fcc5bbfa40af3339463e5e6f1baba Mon Sep 17 00:00:00 2001 From: g11tech Date: Fri, 14 Apr 2023 01:46:07 +0530 Subject: [PATCH 08/53] tx: Update blob tx type to 0x03 (#2636) * tx: Update blob tx type to 0x03 * update in tx factory * fix specs * fix spec * update vm specs * fixes * further fixes --- packages/client/lib/rpc/modules/eth.ts | 2 +- packages/client/lib/service/txpool.ts | 2 +- .../test/net/protocol/ethprotocol.spec.ts | 2 +- .../test/rpc/engine/getBlobsBundleV1.spec.ts | 6 ++--- packages/tx/src/eip4844Transaction.ts | 4 ++-- packages/tx/src/transactionFactory.ts | 4 ++-- packages/tx/test/eip3860.spec.ts | 2 +- packages/tx/test/eip4844.spec.ts | 22 +++++++++---------- packages/vm/test/api/runTx.spec.ts | 2 +- packages/vm/test/api/utils.ts | 2 +- 10 files changed, 24 insertions(+), 24 deletions(-) diff --git a/packages/client/lib/rpc/modules/eth.ts b/packages/client/lib/rpc/modules/eth.ts index 91060ffa60..283ea609c7 100644 --- a/packages/client/lib/rpc/modules/eth.ts +++ b/packages/client/lib/rpc/modules/eth.ts @@ -905,7 +905,7 @@ export class Eth { let tx try { const txBuf = hexStringToBytes(serializedTx) - if (txBuf[0] === 0x05) { + if (txBuf[0] === 0x03) { // Blob Transactions sent over RPC are expected to be in Network Wrapper format tx = BlobEIP4844Transaction.fromSerializedBlobTxNetworkWrapper(txBuf, { common }) } else { diff --git a/packages/client/lib/service/txpool.ts b/packages/client/lib/service/txpool.ts index 930965a643..4779cf7fd6 100644 --- a/packages/client/lib/service/txpool.ts +++ b/packages/client/lib/service/txpool.ts @@ -661,7 +661,7 @@ export class TxPool { tip: (tx as AccessListEIP2930Transaction).gasPrice, } case 2: - case 5: + case 3: return { maxFee: (tx as FeeMarketEIP1559Transaction).maxFeePerGas, tip: (tx as FeeMarketEIP1559Transaction).maxPriorityFeePerGas, diff --git a/packages/client/test/net/protocol/ethprotocol.spec.ts b/packages/client/test/net/protocol/ethprotocol.spec.ts index d2801c14f0..849650b389 100644 --- a/packages/client/test/net/protocol/ethprotocol.spec.ts +++ b/packages/client/test/net/protocol/ethprotocol.spec.ts @@ -227,7 +227,7 @@ tape('[EthProtocol]', (t) => { const legacyTx = TransactionFactory.fromTxData({ type: 0 }) const eip2929Tx = TransactionFactory.fromTxData({ type: 1 }) const eip1559Tx = TransactionFactory.fromTxData({ type: 2 }) - const blobTx = TransactionFactory.fromTxData({ type: 5 }, { common: config.chainCommon }) + const blobTx = TransactionFactory.fromTxData({ type: 3 }, { common: config.chainCommon }) const res = p.encode(p.messages.filter((message) => message.name === 'Transactions')[0], [ legacyTx, eip2929Tx, diff --git a/packages/client/test/rpc/engine/getBlobsBundleV1.spec.ts b/packages/client/test/rpc/engine/getBlobsBundleV1.spec.ts index f6a25ec396..b14d981581 100644 --- a/packages/client/test/rpc/engine/getBlobsBundleV1.spec.ts +++ b/packages/client/test/rpc/engine/getBlobsBundleV1.spec.ts @@ -76,7 +76,7 @@ tape(`${method}: call with known payload`, async (t) => { await baseRequest(t, server, req, 200, expectRes, false) const tx = TransactionFactory.fromTxData( { - type: 0x05, + type: 0x03, versionedHashes: [], maxFeePerDataGas: 1n, maxFeePerGas: 10000000000n, @@ -92,7 +92,7 @@ tape(`${method}: call with known payload`, async (t) => { expectRes = (res: any) => { t.equal( res.body.result.executionPayload.blockHash, - '0x467ffd05100e34088fbc3eee3966304a3330ac37fe5d85c1873a867f514112e6', + '0x4f3068842f4977e1358719f03868cae636e654eca60cf97a1b5619aa006b7185', 'built expected block' ) } @@ -102,7 +102,7 @@ tape(`${method}: call with known payload`, async (t) => { expectRes = (res: any) => { t.equal( res.body.result.blockHash, - '0x467ffd05100e34088fbc3eee3966304a3330ac37fe5d85c1873a867f514112e6', + '0x4f3068842f4977e1358719f03868cae636e654eca60cf97a1b5619aa006b7185', 'got expected blockHash' ) } diff --git a/packages/tx/src/eip4844Transaction.ts b/packages/tx/src/eip4844Transaction.ts index 6e270bf8f4..5510fec7cb 100644 --- a/packages/tx/src/eip4844Transaction.ts +++ b/packages/tx/src/eip4844Transaction.ts @@ -37,7 +37,7 @@ import type { import type { ValueOf } from '@chainsafe/ssz' import type { Common } from '@ethereumjs/common' -const TRANSACTION_TYPE = 0x05 +const TRANSACTION_TYPE = 0x03 const TRANSACTION_TYPE_BYTES = hexStringToBytes(TRANSACTION_TYPE.toString(16).padStart(2, '0')) const validateBlobTransactionNetworkWrapper = ( @@ -366,7 +366,7 @@ export class BlobEIP4844Transaction extends BaseTransaction Uint8Array.from(proof)) ?? [], }) - return concatBytes(new Uint8Array([0x05]), serializedTxWrapper) + return concatBytes(new Uint8Array([0x03]), serializedTxWrapper) } getMessageToSign(hashMessage: false): Uint8Array | Uint8Array[] diff --git a/packages/tx/src/transactionFactory.ts b/packages/tx/src/transactionFactory.ts index 5a76e5d91b..7777b4897c 100644 --- a/packages/tx/src/transactionFactory.ts +++ b/packages/tx/src/transactionFactory.ts @@ -41,7 +41,7 @@ export class TransactionFactory { return AccessListEIP2930Transaction.fromTxData(txData, txOptions) } else if (txType === 2) { return FeeMarketEIP1559Transaction.fromTxData(txData, txOptions) - } else if (txType === 5) { + } else if (txType === 3) { return BlobEIP4844Transaction.fromTxData(txData, txOptions) } else { throw new Error(`Tx instantiation with type ${txType} not supported`) @@ -63,7 +63,7 @@ export class TransactionFactory { return AccessListEIP2930Transaction.fromSerializedTx(data, txOptions) case 2: return FeeMarketEIP1559Transaction.fromSerializedTx(data, txOptions) - case 5: + case 3: return BlobEIP4844Transaction.fromSerializedTx(data, txOptions) default: throw new Error(`TypedTransaction with ID ${data[0]} unknown`) diff --git a/packages/tx/test/eip3860.spec.ts b/packages/tx/test/eip3860.spec.ts index b1cbaf92a6..42cd983e28 100644 --- a/packages/tx/test/eip3860.spec.ts +++ b/packages/tx/test/eip3860.spec.ts @@ -11,7 +11,7 @@ const common = new Common({ }) const maxInitCodeSize = common.param('vm', 'maxInitCodeSize') -const txTypes = [0, 1, 2, 5] +const txTypes = [0, 1, 2, 3] const addressZero = Address.zero() tape('[EIP3860 tests]', function (t) { diff --git a/packages/tx/test/eip4844.spec.ts b/packages/tx/test/eip4844.spec.ts index 33feeaf384..5fb7c583f5 100644 --- a/packages/tx/test/eip4844.spec.ts +++ b/packages/tx/test/eip4844.spec.ts @@ -34,19 +34,19 @@ tape('EIP4844 constructor tests - valid scenarios', (t) => { t.end() } else { const txData = { - type: 0x05, + type: 0x03, versionedHashes: [concatBytes(new Uint8Array([1]), randomBytes(31))], maxFeePerDataGas: 1n, } const tx = BlobEIP4844Transaction.fromTxData(txData, { common }) - t.equal(tx.type, 5, 'successfully instantiated a blob transaction from txData') + t.equal(tx.type, 3, 'successfully instantiated a blob transaction from txData') const factoryTx = TransactionFactory.fromTxData(txData, { common }) - t.equal(factoryTx.type, 5, 'instantiated a blob transaction from the tx factory') + t.equal(factoryTx.type, 3, 'instantiated a blob transaction from the tx factory') const serializedTx = tx.serialize() - t.equal(serializedTx[0], 5, 'successfully serialized a blob tx') + t.equal(serializedTx[0], 3, 'successfully serialized a blob tx') const deserializedTx = BlobEIP4844Transaction.fromSerializedTx(serializedTx, { common }) - t.equal(deserializedTx.type, 5, 'deserialized a blob tx') + t.equal(deserializedTx.type, 3, 'deserialized a blob tx') const signedTx = tx.sign(pk) const sender = signedTx.getSenderAddress().toString() @@ -66,7 +66,7 @@ tape('fromTxData using from a json', (t) => { t.end() } else { const txData = { - type: '0x5', + type: '0x3', nonce: '0x0', gasPrice: null, maxPriorityFeePerGas: '0x12a05f200', @@ -84,9 +84,9 @@ tape('fromTxData using from a json', (t) => { versionedHashes: ['0x01b0a4cdd5f55589f5c5b4d46c76704bb6ce95c0a8c09f77f197a57808dded28'], kzgAggregatedProof: '0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - hash: 'd5455662e76b193a84ce57d4c0a3b6fd609fdfca21cc93b93408de62be3c5708', + hash: '35cfcdb43774134e8a8b05e936222c35bc5c68b9aa672453eedf5897213b4a6b', serialized: - '054500000000a7585eaecd6b446d7e358fdc244d8d4bea5c4ff233ed4d5a480678c03e83838af857b5c220d93590d9ff9871c910691942e12ea3bdfcb5c084cf502a42baa268b357870200000000000000000000000000000000000000000000000000000000000000000000000000f2052a0100000000000000000000000000000000000000000000000000000000f2052a010000000000000000000000000000000000000000000000000000005034030000000000c00000004e61bc0000000000000000000000000000000000000000000000000000000000d5000000d5000000005ed0b200000000000000000000000000000000000000000000000000000000d500000001ffb38a7a99e3e2335be83fc74b7faa19d553124301b0a4cdd5f55589f5c5b4d46c76704bb6ce95c0a8c09f77f197a57808dded28', + '034500000000a7585eaecd6b446d7e358fdc244d8d4bea5c4ff233ed4d5a480678c03e83838af857b5c220d93590d9ff9871c910691942e12ea3bdfcb5c084cf502a42baa268b357870200000000000000000000000000000000000000000000000000000000000000000000000000f2052a0100000000000000000000000000000000000000000000000000000000f2052a010000000000000000000000000000000000000000000000000000005034030000000000c00000004e61bc0000000000000000000000000000000000000000000000000000000000d5000000d5000000005ed0b200000000000000000000000000000000000000000000000000000000d500000001ffb38a7a99e3e2335be83fc74b7faa19d553124301b0a4cdd5f55589f5c5b4d46c76704bb6ce95c0a8c09f77f197a57808dded28', } const c = common.copy() c['_chainParams'] = Object.assign({}, common['_chainParams'], { @@ -113,7 +113,7 @@ tape('EIP4844 constructor tests - invalid scenarios', (t) => { t.end() } else { const baseTxData = { - type: 0x05, + type: 0x03, maxFeePerDataGas: 1n, } const shortVersionHash = { @@ -184,7 +184,7 @@ tape('Network wrapper tests', async (t) => { t.equal( deserializedTx.type, - 0x05, + 0x03, 'successfully deserialized a blob transaction network wrapper' ) t.equal(deserializedTx.blobs?.length, blobs.length, 'contains the correct number of blobs') @@ -309,7 +309,7 @@ tape('hash() and signature verification', async (t) => { ) t.equal( bytesToHex(unsignedTx.unsignedHash()), - '0fcee5b30088a9c96b4990a3914002736a50f42468209d65a93badd3d1cd0677', + 'a99daca5e246f242df985eca984d17ce1a510a780fdd5221d5635f96a5a1bebc', 'produced the correct transaction hash' ) const signedTx = unsignedTx.sign( diff --git a/packages/vm/test/api/runTx.spec.ts b/packages/vm/test/api/runTx.spec.ts index 185fe02210..5ccdbc38c7 100644 --- a/packages/vm/test/api/runTx.spec.ts +++ b/packages/vm/test/api/runTx.spec.ts @@ -913,7 +913,7 @@ tape('EIP 4844 transaction tests', async (t) => { const blockchain = await Blockchain.create({ validateBlocks: false, validateConsensus: false }) const vm = await VM.create({ common, blockchain }) - const tx = getTransaction(common, 5, true) + const tx = getTransaction(common, 3, true) const block = Block.fromBlockData( { diff --git a/packages/vm/test/api/utils.ts b/packages/vm/test/api/utils.ts index d6abd21eac..530ed405b9 100644 --- a/packages/vm/test/api/utils.ts +++ b/packages/vm/test/api/utils.ts @@ -89,7 +89,7 @@ export function getTransaction( txParams['gasPrice'] = undefined txParams['maxFeePerGas'] = BigInt(100) txParams['maxPriorityFeePerGas'] = BigInt(10) - } else if (txType === 5) { + } else if (txType === 3) { txParams['gasPrice'] = undefined txParams['maxFeePerGas'] = BigInt(1000000000) txParams['maxPriorityFeePerGas'] = BigInt(10) From a14669d400f8a5d41e99f87fe284ecfb4817e343 Mon Sep 17 00:00:00 2001 From: g11tech Date: Fri, 14 Apr 2023 19:06:16 +0530 Subject: [PATCH 09/53] tx: Fix the deserialization of blob tx and add no empty blobs validation (#2640) --- packages/tx/src/eip4844Transaction.ts | 7 +++++- packages/tx/test/eip4844.spec.ts | 36 +++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/packages/tx/src/eip4844Transaction.ts b/packages/tx/src/eip4844Transaction.ts index 5510fec7cb..a84e941d55 100644 --- a/packages/tx/src/eip4844Transaction.ts +++ b/packages/tx/src/eip4844Transaction.ts @@ -50,6 +50,10 @@ const validateBlobTransactionNetworkWrapper = ( if (!(versionedHashes.length === blobs.length && blobs.length === commitments.length)) { throw new Error('Number of versionedHashes, blobs, and commitments not all equal') } + if (versionedHashes.length === 0) { + throw new Error('Invalid transaction with empty blobs') + } + try { kzg.verifyBlobKzgProofBatch(blobs, commitments, kzgProofs) } catch (e) { @@ -265,7 +269,8 @@ export class BlobEIP4844Transaction extends BaseTransaction { } }) +tape('fromSerializedTx - from bytes', (t) => { + const serializedBlobTx = hexToBytes( + '034500000001a34a3d6d997350dfa6c9645624b0a02b1c79591fe90d574f2ee5599103fbcff03e2156483cc73cac5648fa0348b487c90cc2713a7d636df7335333ca1b18c650010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000ff0000000000000000000000000000000000000000000000000000000000000040420f0000000000c00000000000000000000000000000000000000000000000000000000000000000000000d5000000d5000000e803000000000000000000000000000000000000000000000000000000000000d5000000013da33b9a0894b908ddbb00d96399e506515a1009016ebc7b0ffa71dc019db13caaf539032134295cc5e652fa5b82c8e67f0fd9e1' + ) + try { + BlobEIP4844Transaction.fromSerializedTx(serializedBlobTx, { common }) + t.pass('Should correctly deserialize blob tx from bytes') + } catch (e) { + t.fail(`Could not deserialize blob tx from bytes, Error: ${(e as Error).message}`) + } + t.end() +}) + tape('EIP4844 constructor tests - invalid scenarios', (t) => { if (isBrowser() === true) { t.end() @@ -200,6 +213,29 @@ tape('Network wrapper tests', async (t) => { 'has the same hash as the network wrapper version' ) + const txWithEmptyBlob = BlobEIP4844Transaction.fromTxData( + { + versionedHashes: [], + blobs: [], + kzgCommitments: [], + kzgProofs: [], + maxFeePerDataGas: 100000000n, + gasLimit: 0xffffffn, + to: randomBytes(20), + }, + { common } + ) + + const serializedWithEmptyBlob = txWithEmptyBlob.serializeNetworkWrapper() + t.throws( + () => + BlobEIP4844Transaction.fromSerializedBlobTxNetworkWrapper(serializedWithEmptyBlob, { + common, + }), + (err: any) => err.message === 'Invalid transaction with empty blobs', + 'throws a transaction with no blobs' + ) + const txWithMissingBlob = BlobEIP4844Transaction.fromTxData( { versionedHashes, From 158b750fe17ab27cde64115c1fefbd0a2dde8a89 Mon Sep 17 00:00:00 2001 From: acolytec3 Date: Fri, 14 Apr 2023 14:49:25 -0400 Subject: [PATCH 10/53] Add dataGasUsed to txReceipt and result (#2620) * add dataGasUsed to txReceipt and result * Add tests * Add test for getTransactionReceipt * lint * Address feedback * Remove buffer * Merge fixes and cleanup * add datagasprice to receipt * fix tests * Fix vm browser test config --- package-lock.json | 2 + .../block/test/testdata/4844-hardfork.json | 3 + packages/client/lib/rpc/modules/eth.ts | 22 ++++- .../rpc/eth/getTransactionReceipt.spec.ts | 63 +++++++++++- packages/evm/src/evm.ts | 4 + packages/util/src/kzg.ts | 1 - packages/vm/karma.conf.js | 1 + packages/vm/package.json | 1 + packages/vm/src/runTx.ts | 38 ++++++-- packages/vm/src/types.ts | 24 ++++- packages/vm/test/api/runTx.spec.ts | 96 ++++++++++--------- packages/vm/test/api/utils.ts | 11 ++- 12 files changed, 208 insertions(+), 58 deletions(-) diff --git a/package-lock.json b/package-lock.json index 659ee164f6..0e7b70dcdb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18314,6 +18314,7 @@ "@types/minimist": "^1.2.2", "@types/node-dir": "^0.0.34", "benchmark": "^2.1.4", + "c-kzg": "^2.0.4", "level": "^8.0.0", "memory-level": "^1.0.0", "minimist": "^1.2.5", @@ -19903,6 +19904,7 @@ "@types/minimist": "^1.2.2", "@types/node-dir": "^0.0.34", "benchmark": "^2.1.4", + "c-kzg": "^2.0.4", "debug": "^4.3.3", "ethereum-cryptography": "^1.1.2", "level": "^8.0.0", diff --git a/packages/block/test/testdata/4844-hardfork.json b/packages/block/test/testdata/4844-hardfork.json index 8abe087a97..ac09973c93 100644 --- a/packages/block/test/testdata/4844-hardfork.json +++ b/packages/block/test/testdata/4844-hardfork.json @@ -36,6 +36,9 @@ "0x8A04d14125D0FDCDc742F4A05C051De07232EDa4": { "code": "0x60806040526004361061003f5760003560e01c806301ffc9a714610044578063228951181461008c578063621fd130146101a2578063c5f2892f1461022c575b600080fd5b34801561005057600080fd5b506100786004803603602081101561006757600080fd5b50356001600160e01b031916610253565b604080519115158252519081900360200190f35b6101a0600480360360808110156100a257600080fd5b8101906020810181356401000000008111156100bd57600080fd5b8201836020820111156100cf57600080fd5b803590602001918460018302840111640100000000831117156100f157600080fd5b91939092909160208101903564010000000081111561010f57600080fd5b82018360208201111561012157600080fd5b8035906020019184600183028401116401000000008311171561014357600080fd5b91939092909160208101903564010000000081111561016157600080fd5b82018360208201111561017357600080fd5b8035906020019184600183028401116401000000008311171561019557600080fd5b91935091503561028a565b005b3480156101ae57600080fd5b506101b7610ce6565b6040805160208082528351818301528351919283929083019185019080838360005b838110156101f15781810151838201526020016101d9565b50505050905090810190601f16801561021e5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561023857600080fd5b50610241610cf8565b60408051918252519081900360200190f35b60006001600160e01b031982166301ffc9a760e01b148061028457506001600160e01b03198216638564090760e01b145b92915050565b603086146102c95760405162461bcd60e51b81526004018080602001828103825260268152602001806112516026913960400191505060405180910390fd5b602084146103085760405162461bcd60e51b81526004018080602001828103825260368152602001806111e86036913960400191505060405180910390fd5b606082146103475760405162461bcd60e51b81526004018080602001828103825260298152602001806112c46029913960400191505060405180910390fd5b670de0b6b3a764000034101561038e5760405162461bcd60e51b815260040180806020018281038252602681526020018061129e6026913960400191505060405180910390fd5b633b9aca003406156103d15760405162461bcd60e51b815260040180806020018281038252603381526020018061121e6033913960400191505060405180910390fd5b633b9aca00340467ffffffffffffffff81111561041f5760405162461bcd60e51b81526004018080602001828103825260278152602001806112776027913960400191505060405180910390fd5b606061042a82610fc6565b90507f649bbc62d0e31342afea4e5cd82d4049e7e1ee912fc0889aa790803be39038c589898989858a8a61045f602054610fc6565b6040805160a0808252810189905290819060208201908201606083016080840160c085018e8e80828437600083820152601f01601f191690910187810386528c815260200190508c8c808284376000838201819052601f909101601f191690920188810386528c5181528c51602091820193918e019250908190849084905b838110156104f65781810151838201526020016104de565b50505050905090810190601f1680156105235780820380516001836020036101000a031916815260200191505b5086810383528881526020018989808284376000838201819052601f909101601f19169092018881038452895181528951602091820193918b019250908190849084905b8381101561057f578181015183820152602001610567565b50505050905090810190601f1680156105ac5780820380516001836020036101000a031916815260200191505b509d505050505050505050505050505060405180910390a1600060028a8a600060801b604051602001808484808284376fffffffffffffffffffffffffffffffff199094169190930190815260408051600f19818403018152601090920190819052815191955093508392506020850191508083835b602083106106415780518252601f199092019160209182019101610622565b51815160209384036101000a60001901801990921691161790526040519190930194509192505080830381855afa158015610680573d6000803e3d6000fd5b5050506040513d602081101561069557600080fd5b5051905060006002806106ab6040848a8c61114a565b6040516020018083838082843780830192505050925050506040516020818303038152906040526040518082805190602001908083835b602083106107015780518252601f1990920191602091820191016106e2565b51815160209384036101000a60001901801990921691161790526040519190930194509192505080830381855afa158015610740573d6000803e3d6000fd5b5050506040513d602081101561075557600080fd5b50516002610766896040818d61114a565b60405160009060200180848480828437919091019283525050604080518083038152602092830191829052805190945090925082918401908083835b602083106107c15780518252601f1990920191602091820191016107a2565b51815160209384036101000a60001901801990921691161790526040519190930194509192505080830381855afa158015610800573d6000803e3d6000fd5b5050506040513d602081101561081557600080fd5b5051604080516020818101949094528082019290925280518083038201815260609092019081905281519192909182918401908083835b6020831061086b5780518252601f19909201916020918201910161084c565b51815160209384036101000a60001901801990921691161790526040519190930194509192505080830381855afa1580156108aa573d6000803e3d6000fd5b5050506040513d60208110156108bf57600080fd5b50516040805160208101858152929350600092600292839287928f928f92018383808284378083019250505093505050506040516020818303038152906040526040518082805190602001908083835b6020831061092e5780518252601f19909201916020918201910161090f565b51815160209384036101000a60001901801990921691161790526040519190930194509192505080830381855afa15801561096d573d6000803e3d6000fd5b5050506040513d602081101561098257600080fd5b50516040518651600291889160009188916020918201918291908601908083835b602083106109c25780518252601f1990920191602091820191016109a3565b6001836020036101000a0380198251168184511680821785525050505050509050018367ffffffffffffffff191667ffffffffffffffff1916815260180182815260200193505050506040516020818303038152906040526040518082805190602001908083835b60208310610a495780518252601f199092019160209182019101610a2a565b51815160209384036101000a60001901801990921691161790526040519190930194509192505080830381855afa158015610a88573d6000803e3d6000fd5b5050506040513d6020811015610a9d57600080fd5b5051604080516020818101949094528082019290925280518083038201815260609092019081905281519192909182918401908083835b60208310610af35780518252601f199092019160209182019101610ad4565b51815160209384036101000a60001901801990921691161790526040519190930194509192505080830381855afa158015610b32573d6000803e3d6000fd5b5050506040513d6020811015610b4757600080fd5b50519050858114610b895760405162461bcd60e51b81526004018080602001828103825260548152602001806111946054913960600191505060405180910390fd5b60205463ffffffff11610bcd5760405162461bcd60e51b81526004018080602001828103825260218152602001806111736021913960400191505060405180910390fd5b602080546001019081905560005b6020811015610cda578160011660011415610c0d578260008260208110610bfe57fe5b015550610cdd95505050505050565b600260008260208110610c1c57fe5b01548460405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b60208310610c745780518252601f199092019160209182019101610c55565b51815160209384036101000a60001901801990921691161790526040519190930194509192505080830381855afa158015610cb3573d6000803e3d6000fd5b5050506040513d6020811015610cc857600080fd5b50519250600282049150600101610bdb565b50fe5b50505050505050565b6060610cf3602054610fc6565b905090565b6020546000908190815b6020811015610ea9578160011660011415610ddb57600260008260208110610d2657fe5b01548460405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b60208310610d7e5780518252601f199092019160209182019101610d5f565b51815160209384036101000a60001901801990921691161790526040519190930194509192505080830381855afa158015610dbd573d6000803e3d6000fd5b5050506040513d6020811015610dd257600080fd5b50519250610e9b565b60028360218360208110610deb57fe5b015460405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b60208310610e425780518252601f199092019160209182019101610e23565b51815160209384036101000a60001901801990921691161790526040519190930194509192505080830381855afa158015610e81573d6000803e3d6000fd5b5050506040513d6020811015610e9657600080fd5b505192505b600282049150600101610d02565b50600282610eb8602054610fc6565b600060401b6040516020018084815260200183805190602001908083835b60208310610ef55780518252601f199092019160209182019101610ed6565b51815160209384036101000a600019018019909216911617905267ffffffffffffffff199590951692019182525060408051808303600719018152601890920190819052815191955093508392850191508083835b60208310610f695780518252601f199092019160209182019101610f4a565b51815160209384036101000a60001901801990921691161790526040519190930194509192505080830381855afa158015610fa8573d6000803e3d6000fd5b5050506040513d6020811015610fbd57600080fd5b50519250505090565b60408051600880825281830190925260609160208201818036833701905050905060c082901b8060071a60f81b8260008151811061100057fe5b60200101906001600160f81b031916908160001a9053508060061a60f81b8260018151811061102b57fe5b60200101906001600160f81b031916908160001a9053508060051a60f81b8260028151811061105657fe5b60200101906001600160f81b031916908160001a9053508060041a60f81b8260038151811061108157fe5b60200101906001600160f81b031916908160001a9053508060031a60f81b826004815181106110ac57fe5b60200101906001600160f81b031916908160001a9053508060021a60f81b826005815181106110d757fe5b60200101906001600160f81b031916908160001a9053508060011a60f81b8260068151811061110257fe5b60200101906001600160f81b031916908160001a9053508060001a60f81b8260078151811061112d57fe5b60200101906001600160f81b031916908160001a90535050919050565b60008085851115611159578182fd5b83861115611165578182fd5b505082019391909203915056fe4465706f736974436f6e74726163743a206d65726b6c6520747265652066756c6c4465706f736974436f6e74726163743a207265636f6e7374727563746564204465706f7369744461746120646f6573206e6f74206d6174636820737570706c696564206465706f7369745f646174615f726f6f744465706f736974436f6e74726163743a20696e76616c6964207769746864726177616c5f63726564656e7469616c73206c656e6774684465706f736974436f6e74726163743a206465706f7369742076616c7565206e6f74206d756c7469706c65206f6620677765694465706f736974436f6e74726163743a20696e76616c6964207075626b6579206c656e6774684465706f736974436f6e74726163743a206465706f7369742076616c756520746f6f20686967684465706f736974436f6e74726163743a206465706f7369742076616c756520746f6f206c6f774465706f736974436f6e74726163743a20696e76616c6964207369676e6174757265206c656e677468a164736f6c634300060b000a", "balance": "0x0" + }, + "0xcde098d93535445768e8a2345a2f869139f45641": { + "balance": "0x6d6172697573766477000000" } }, "number": "0x0", diff --git a/packages/client/lib/rpc/modules/eth.ts b/packages/client/lib/rpc/modules/eth.ts index 283ea609c7..37c2695433 100644 --- a/packages/client/lib/rpc/modules/eth.ts +++ b/packages/client/lib/rpc/modules/eth.ts @@ -26,7 +26,13 @@ import type { Block, JsonRpcBlock } from '@ethereumjs/block' import type { Log } from '@ethereumjs/evm' import type { Proof } from '@ethereumjs/statemanager' import type { FeeMarketEIP1559Transaction, Transaction, TypedTransaction } from '@ethereumjs/tx' -import type { PostByzantiumTxReceipt, PreByzantiumTxReceipt, TxReceipt, VM } from '@ethereumjs/vm' +import type { + EIP4844BlobTxReceipt, + PostByzantiumTxReceipt, + PreByzantiumTxReceipt, + TxReceipt, + VM, +} from '@ethereumjs/vm' type GetLogsParams = { fromBlock?: string // QUANTITY, block number or "earliest" or "latest" (default: "latest") @@ -57,6 +63,8 @@ type JsonRpcReceipt = { // It also returns either: root?: string // DATA, 32 bytes of post-transaction stateroot (pre Byzantium) status?: string // QUANTITY, either 1 (success) or 0 (failure) + dataGasUsed?: string // QUANTITY, data gas consumed by transaction (if blob transaction) + dataGasPrice?: string // QUAntity, data gas price for block including this transaction (if blob transaction) } type JsonRpcLog = { removed: boolean // TAG - true when the log was removed, due to a chain reorganization. false if it's a valid log. @@ -152,7 +160,9 @@ const jsonRpcReceipt = async ( tx: TypedTransaction, txIndex: number, logIndex: number, - contractAddress?: Address + contractAddress?: Address, + dataGasUsed?: bigint, + dataGasPrice?: bigint ): Promise => ({ transactionHash: bytesToPrefixedHexString(tx.hash()), transactionIndex: intToHex(txIndex), @@ -176,6 +186,8 @@ const jsonRpcReceipt = async ( ((receipt as PostByzantiumTxReceipt).status as unknown) instanceof Uint8Array ? intToHex((receipt as PostByzantiumTxReceipt).status) : undefined, + dataGasUsed: dataGasUsed !== undefined ? bigIntToHex(dataGasUsed) : undefined, + dataGasPrice: dataGasPrice !== undefined ? bigIntToHex(dataGasPrice) : undefined, }) /** @@ -763,7 +775,9 @@ export class Eth { root: parentBlock.header.stateRoot, skipBlockValidation: true, }) + const { totalGasSpent, createdAddress } = runBlockResult.results[txIndex] + const { dataGasPrice, dataGasUsed } = runBlockResult.receipts[txIndex] as EIP4844BlobTxReceipt return await jsonRpcReceipt( receipt, totalGasSpent, @@ -772,7 +786,9 @@ export class Eth { tx, txIndex, logIndex, - createdAddress + createdAddress, + dataGasUsed, + dataGasPrice ) } catch (error: any) { throw { diff --git a/packages/client/test/rpc/eth/getTransactionReceipt.spec.ts b/packages/client/test/rpc/eth/getTransactionReceipt.spec.ts index 405cf98f3c..f7c2a097af 100644 --- a/packages/client/test/rpc/eth/getTransactionReceipt.spec.ts +++ b/packages/client/test/rpc/eth/getTransactionReceipt.spec.ts @@ -1,5 +1,14 @@ -import { FeeMarketEIP1559Transaction, Transaction } from '@ethereumjs/tx' -import { bytesToPrefixedHexString } from '@ethereumjs/util' +import { Common, Hardfork } from '@ethereumjs/common' +import { BlobEIP4844Transaction, FeeMarketEIP1559Transaction, Transaction } from '@ethereumjs/tx' +import { + blobsToCommitments, + bytesToPrefixedHexString, + commitmentsToVersionedHashes, + getBlobs, + initKZG, + randomBytes, +} from '@ethereumjs/util' +import * as kzg from 'c-kzg' import * as tape from 'tape' import { @@ -78,3 +87,53 @@ tape(`${method}: call with unknown tx hash`, async (t) => { } await baseRequest(t, server, req, 200, expectRes) }) + +tape(`${method}: get dataGasUsed/dataGasPrice in blob tx receipt`, async (t) => { + const isBrowser = new Function('try {return this===window;}catch(e){ return false;}') + if (isBrowser() === true) { + t.end() + } else { + try { + // Verified KZG is loaded correctly -- NOOP if throws + 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', + hardfork: Hardfork.ShardingForkDev, + }) + const { chain, execution, server } = await setupChain(gethGenesis, 'customChain') + common.setHardfork(Hardfork.ShardingForkDev) + + const blobs = getBlobs('hello world') + const commitments = blobsToCommitments(blobs) + const versionedHashes = commitmentsToVersionedHashes(commitments) + const proofs = blobs.map((blob, ctx) => kzg.computeBlobKzgProof(blob, commitments[ctx])) + const tx = BlobEIP4844Transaction.fromTxData( + { + versionedHashes, + blobs, + kzgCommitments: commitments, + kzgProofs: proofs, + maxFeePerDataGas: 1000000n, + gasLimit: 0xffffn, + maxFeePerGas: 10000000n, + maxPriorityFeePerGas: 1000000n, + to: randomBytes(20), + nonce: 0n, + }, + { common } + ).sign(dummy.privKey) + + await runBlockWithTxs(chain, execution, [tx], true) + + const req = params(method, [bytesToPrefixedHexString(tx.hash())]) + const expectRes = (res: any) => { + t.equal(res.body.result.dataGasUsed, '0x20000', 'receipt has correct data gas usage') + t.equal(res.body.result.dataGasPrice, '0x1', 'receipt has correct data gas price') + } + + await baseRequest(t, server, req, 200, expectRes) + } +}) diff --git a/packages/evm/src/evm.ts b/packages/evm/src/evm.ts index 8bfca5615d..6fdf812b40 100644 --- a/packages/evm/src/evm.ts +++ b/packages/evm/src/evm.ts @@ -1043,6 +1043,10 @@ export interface ExecResult { * The gas refund counter */ gasRefund?: bigint + /** + * Amount of data gas consumed by the transaction + */ + dataGasUsed?: bigint } export function OOGResult(gasLimit: bigint): ExecResult { diff --git a/packages/util/src/kzg.ts b/packages/util/src/kzg.ts index 05c48fd5f9..f0929f872c 100644 --- a/packages/util/src/kzg.ts +++ b/packages/util/src/kzg.ts @@ -37,6 +37,5 @@ export let kzg: Kzg = { */ export function initKZG(kzgLib: Kzg, trustedSetupPath: string) { kzg = kzgLib - kzg.loadTrustedSetup(trustedSetupPath) } diff --git a/packages/vm/karma.conf.js b/packages/vm/karma.conf.js index 96b97bb756..0e3ecd7941 100644 --- a/packages/vm/karma.conf.js +++ b/packages/vm/karma.conf.js @@ -35,6 +35,7 @@ module.exports = function (config) { '../../node_modules/@chainsafe/as-sha256/lib/hashObject.js', }, }, + ignore: ['c-kzg', 'safer-buffer'], }, }, diff --git a/packages/vm/package.json b/packages/vm/package.json index 2a0dbf5df1..29c0c0f7d8 100644 --- a/packages/vm/package.json +++ b/packages/vm/package.json @@ -78,6 +78,7 @@ "@types/minimist": "^1.2.2", "@types/node-dir": "^0.0.34", "benchmark": "^2.1.4", + "c-kzg": "^2.0.4", "level": "^8.0.0", "memory-level": "^1.0.0", "minimist": "^1.2.5", diff --git a/packages/vm/src/runTx.ts b/packages/vm/src/runTx.ts index 43b32f2ff1..ec5d15b6d2 100644 --- a/packages/vm/src/runTx.ts +++ b/packages/vm/src/runTx.ts @@ -17,6 +17,7 @@ import { Bloom } from './bloom' import type { AfterTxEvent, BaseTxReceipt, + EIP4844BlobTxReceipt, PostByzantiumTxReceipt, PreByzantiumTxReceipt, RunTxOpts, @@ -474,6 +475,11 @@ async function _runTx(this: VM, opts: RunTxOpts): Promise { debugGas(`tx add baseFee ${txBaseFee} to totalGasSpent (-> ${results.totalGasSpent})`) } + // Add data gas used to result + if (tx.type === 3) { + results.dataGasUsed = totalDataGas + } + // Process any gas refund let gasRefund = results.execResult.gasRefund ?? BigInt(0) results.gasRefund = gasRefund @@ -554,7 +560,13 @@ async function _runTx(this: VM, opts: RunTxOpts): Promise { // Generate the tx receipt const gasUsed = opts.blockGasUsed !== undefined ? opts.blockGasUsed : block.header.gasUsed const cumulativeGasUsed = gasUsed + results.totalGasSpent - results.receipt = await generateTxReceipt.bind(this)(tx, results, cumulativeGasUsed) + results.receipt = await generateTxReceipt.bind(this)( + tx, + results, + cumulativeGasUsed, + totalDataGas, + dataGasPrice + ) /** * The `afterTx` event @@ -603,12 +615,16 @@ function txLogsBloom(logs?: any[]): Bloom { * @param tx The transaction * @param txResult The tx result * @param cumulativeGasUsed The gas used in the block including this tx + * @param dataGasUsed The data gas used in the tx + * @param dataGasPrice The data gas price for the block including this tx */ export async function generateTxReceipt( this: VM, tx: TypedTransaction, txResult: RunTxResult, - cumulativeGasUsed: bigint + cumulativeGasUsed: bigint, + dataGasUsed?: bigint, + dataGasPrice?: bigint ): Promise { const baseReceipt: BaseTxReceipt = { cumulativeBlockGasUsed: cumulativeGasUsed, @@ -645,12 +661,20 @@ export async function generateTxReceipt( } } else { // Typed EIP-2718 Transaction - receipt = { - status: txResult.execResult.exceptionError !== undefined ? 0 : 1, - ...baseReceipt, - } as PostByzantiumTxReceipt + if (tx.type === 3) { + receipt = { + dataGasUsed, + dataGasPrice, + status: txResult.execResult.exceptionError ? 0 : 1, + ...baseReceipt, + } as EIP4844BlobTxReceipt + } else { + receipt = { + status: txResult.execResult.exceptionError ? 0 : 1, + ...baseReceipt, + } as PostByzantiumTxReceipt + } } - return receipt } diff --git a/packages/vm/src/types.ts b/packages/vm/src/types.ts index ff498c6250..4c949a3365 100644 --- a/packages/vm/src/types.ts +++ b/packages/vm/src/types.ts @@ -6,7 +6,7 @@ import type { EEIInterface, EVMInterface, EVMResult, Log } from '@ethereumjs/evm import type { StateManager } from '@ethereumjs/statemanager' import type { AccessList, TypedTransaction } from '@ethereumjs/tx' import type { BigIntLike, WithdrawalData } from '@ethereumjs/util' -export type TxReceipt = PreByzantiumTxReceipt | PostByzantiumTxReceipt +export type TxReceipt = PreByzantiumTxReceipt | PostByzantiumTxReceipt | EIP4844BlobTxReceipt /** * Abstract interface with common transaction receipt fields @@ -48,6 +48,23 @@ export interface PostByzantiumTxReceipt extends BaseTxReceipt { status: 0 | 1 } +export interface EIP4844BlobTxReceipt extends PostByzantiumTxReceipt { + /** + * Data gas consumed by a transaction + * + * Note: This value is not included in the receiptRLP used for encoding the receiptsRoot in a block + * and is only provided as part of receipt metadata. + */ + dataGasUsed: bigint + /** + * Data gas price for block transaction was included in + * + * Note: This valus is not included in the `receiptRLP` used for encoding the `receiptsRoot` in a block + * and is only provided as part of receipt metadata. + */ + dataGasPrice: bigint +} + export type VMEvents = { beforeBlock: (data: Block, resolve?: (result?: any) => void) => void afterBlock: (data: AfterBlockEvent, resolve?: (result?: any) => void) => void @@ -383,6 +400,11 @@ export interface RunTxResult extends EVMResult { * The value that accrues to the miner by this transaction */ minerValue: bigint + + /** + * This is the data gas units times the fee per data gas for 4844 transactions + */ + dataGasUsed?: bigint } export interface AfterTxEvent extends RunTxResult { diff --git a/packages/vm/test/api/runTx.spec.ts b/packages/vm/test/api/runTx.spec.ts index 5ccdbc38c7..7fa892e5fd 100644 --- a/packages/vm/test/api/runTx.spec.ts +++ b/packages/vm/test/api/runTx.spec.ts @@ -7,7 +7,8 @@ import { Transaction, TransactionFactory, } from '@ethereumjs/tx' -import { Account, Address, KECCAK256_NULL, MAX_INTEGER } from '@ethereumjs/util' +import { Account, Address, KECCAK256_NULL, MAX_INTEGER, initKZG } from '@ethereumjs/util' +import * as kzg from 'c-kzg' import { hexToBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' @@ -880,23 +881,55 @@ tape( ) tape('EIP 4844 transaction tests', async (t) => { - const genesisJson = require('../../../block/test/testdata/4844-hardfork.json') - const common = Common.fromGethGenesis(genesisJson, { - chain: 'customChain', - hardfork: Hardfork.ShardingForkDev, - }) - common.setHardfork(Hardfork.ShardingForkDev) - const oldGetBlockFunction = Blockchain.prototype.getBlock + // Hack to detect if running in browser or not + const isBrowser = new Function('try {return this===window;}catch(e){ return false;}') + + if (isBrowser() === true) { + t.end() + } else { + initKZG(kzg, __dirname + '/../../../client/lib/trustedSetups/devnet4.txt') + const genesisJson = require('../../../block/test/testdata/4844-hardfork.json') + const common = Common.fromGethGenesis(genesisJson, { + chain: 'customChain', + hardfork: Hardfork.ShardingForkDev, + }) + common.setHardfork(Hardfork.ShardingForkDev) + const oldGetBlockFunction = Blockchain.prototype.getBlock + + // Stub getBlock to produce a valid parent header under EIP 4844 + Blockchain.prototype.getBlock = async () => { + return Block.fromBlockData( + { + header: BlockHeader.fromHeaderData( + { + excessDataGas: 0n, + number: 1, + parentHash: blockchain.genesisBlock.hash(), + }, + { + common, + skipConsensusFormatValidation: true, + } + ), + }, + { + common, + skipConsensusFormatValidation: true, + } + ) + } + const blockchain = await Blockchain.create({ validateBlocks: false, validateConsensus: false }) + const vm = await VM.create({ common, blockchain }) - // Stub getBlock to produce a valid parent header under EIP 4844 - Blockchain.prototype.getBlock = async () => { - return Block.fromBlockData( + const tx = getTransaction(common, 3, true) as BlobEIP4844Transaction + + const block = Block.fromBlockData( { header: BlockHeader.fromHeaderData( { - excessDataGas: 0n, - number: 1, - parentHash: blockchain.genesisBlock.hash(), + excessDataGas: 1n, + number: 2, + parentHash: (await blockchain.getBlock(1n)).hash(), // Faking parent hash with getBlock stub }, { common, @@ -904,35 +937,12 @@ tape('EIP 4844 transaction tests', async (t) => { } ), }, - { - common, - skipConsensusFormatValidation: true, - } + { common, skipConsensusFormatValidation: true } ) + const res = await vm.runTx({ tx, block, skipBalance: true }) + t.ok(res.execResult.exceptionError === undefined, 'simple blob tx run succeeds') + t.equal(res.dataGasUsed, 131072n, 'returns correct data gas used for 1 blob') + Blockchain.prototype.getBlock = oldGetBlockFunction + t.end() } - const blockchain = await Blockchain.create({ validateBlocks: false, validateConsensus: false }) - const vm = await VM.create({ common, blockchain }) - - const tx = getTransaction(common, 3, true) - - const block = Block.fromBlockData( - { - header: BlockHeader.fromHeaderData( - { - excessDataGas: 1n, - number: 2, - parentHash: (await blockchain.getBlock(1n)).hash(), // Faking parent hash with getBlock stub - }, - { - common, - skipConsensusFormatValidation: true, - } - ), - }, - { common, skipConsensusFormatValidation: true } - ) - const res = await vm.runTx({ tx, block, skipBalance: true }) - t.ok(res.execResult.exceptionError === undefined, 'simple blob tx run succeeds') - Blockchain.prototype.getBlock = oldGetBlockFunction - t.end() }) diff --git a/packages/vm/test/api/utils.ts b/packages/vm/test/api/utils.ts index 530ed405b9..8e7c6c6afc 100644 --- a/packages/vm/test/api/utils.ts +++ b/packages/vm/test/api/utils.ts @@ -1,6 +1,7 @@ import { Blockchain } from '@ethereumjs/blockchain' import { TransactionFactory } from '@ethereumjs/tx' -import { Account } from '@ethereumjs/util' +import { Account, blobsToCommitments, computeVersionedHash, getBlobs } from '@ethereumjs/util' +import * as kzg from 'c-kzg' import { hexToBytes } from 'ethereum-cryptography/utils' import { MemoryLevel } from 'memory-level' @@ -94,6 +95,14 @@ export function getTransaction( txParams['maxFeePerGas'] = BigInt(1000000000) txParams['maxPriorityFeePerGas'] = BigInt(10) txParams['maxFeePerDataGas'] = BigInt(100) + txParams['blobs'] = getBlobs('hello world') + txParams['kzgCommitments'] = blobsToCommitments(txParams['blobs']) + txParams['kzgProofs'] = txParams['blobs'].map((blob: Uint8Array, ctx: number) => + kzg.computeBlobKzgProof(blob, txParams['kzgCommitments'][ctx] as Uint8Array) + ) + txParams['versionedHashes'] = txParams['kzgCommitments'].map((commitment: Uint8Array) => + computeVersionedHash(commitment, 0x1) + ) } const tx = TransactionFactory.fromTxData(txParams, { common, freeze: false }) From 7f25e6fe47e6632f06afbc1285c9fc0e5c057dcc Mon Sep 17 00:00:00 2001 From: acolytec3 Date: Sun, 16 Apr 2023 07:08:24 -0400 Subject: [PATCH 11/53] Buffer cleanup (#2638) * Cleanup buffer references * Add noBuffer eslint rule * Change noBuffer to be any use of reference Buffer --- config/eslint.js | 2 ++ eslint/index.js | 12 ++++++++++++ eslint/noBuffer.js | 16 ++++++++++++++++ package-lock.json | 11 +++++++++++ package.json | 3 ++- .../client/lib/sync/fetcher/accountfetcher.ts | 16 +++++++--------- packages/client/test/sim/sharding.spec.ts | 2 +- packages/evm/src/precompiles/0a-bls12-g1add.ts | 4 ++-- packages/evm/src/precompiles/0b-bls12-g1mul.ts | 4 ++-- .../evm/src/precompiles/0c-bls12-g1multiexp.ts | 4 ++-- packages/evm/src/precompiles/0d-bls12-g2add.ts | 4 ++-- packages/evm/src/precompiles/0e-bls12-g2mul.ts | 4 ++-- .../evm/src/precompiles/0f-bls12-g2multiexp.ts | 4 ++-- 13 files changed, 63 insertions(+), 23 deletions(-) create mode 100644 eslint/index.js create mode 100644 eslint/noBuffer.js diff --git a/config/eslint.js b/config/eslint.js index 93eca500df..190241dd76 100644 --- a/config/eslint.js +++ b/config/eslint.js @@ -7,6 +7,7 @@ module.exports = { 'import', 'prettier', 'simple-import-sort', + 'ethereumjs', ], env: { es2020: true, @@ -105,6 +106,7 @@ module.exports = { 'prettier/prettier': 'error', 'simple-import-sort/exports': 'error', 'sort-imports': ['error', { ignoreDeclarationSort: true }], + 'ethereumjs/noBuffer': 'error', }, parserOptions: { extraFileExtensions: ['.json'], diff --git a/eslint/index.js b/eslint/index.js new file mode 100644 index 0000000000..0ca9f414d7 --- /dev/null +++ b/eslint/index.js @@ -0,0 +1,12 @@ +const fs = require('fs') +const path = require('path') + +const ruleFiles = fs + .readdirSync(__dirname) + .filter((file) => file !== 'index.js' && !file.endsWith('test.js')) + +const rules = Object.fromEntries( + ruleFiles.map((file) => [path.basename(file, '.js'), require('./' + file)]) +) + +module.exports = { rules } diff --git a/eslint/noBuffer.js b/eslint/noBuffer.js new file mode 100644 index 0000000000..1a4f0135a2 --- /dev/null +++ b/eslint/noBuffer.js @@ -0,0 +1,16 @@ +// @ts-no-check +/** @type {import('eslint').Rule.RuleModule} */ +module.exports = { + create(context) { + return { + Identifier: function (node) { + if (node.name === 'Buffer') { + context.report({ + node: node.parent, + message: 'No Buffers - use Uint8Array instead', + }) + } + }, + } + }, +} diff --git a/package-lock.json b/package-lock.json index 0e7b70dcdb..9153661555 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,6 +19,7 @@ "eslint-config-prettier": "8.5.0", "eslint-config-typestrict": "1.0.5", "eslint-formatter-codeframe": "7.32.1", + "eslint-plugin-ethereumjs": "file:./eslint", "eslint-plugin-github": "4.3.7", "eslint-plugin-implicit-dependencies": "1.1.1", "eslint-plugin-import": "2.26.0", @@ -45,6 +46,9 @@ "npm": ">=7" } }, + "eslint": { + "dev": true + }, "node_modules/@ampproject/remapping": { "version": "2.2.0", "dev": true, @@ -6763,6 +6767,10 @@ "eslint": ">=4.19.1" } }, + "node_modules/eslint-plugin-ethereumjs": { + "resolved": "eslint", + "link": true + }, "node_modules/eslint-plugin-filenames": { "version": "1.3.2", "dev": true, @@ -23270,6 +23278,9 @@ "ignore": "^5.0.5" } }, + "eslint-plugin-ethereumjs": { + "version": "file:eslint" + }, "eslint-plugin-filenames": { "version": "1.3.2", "dev": true, diff --git a/package.json b/package.json index 56981d3f32..6b077f8392 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,8 @@ "ts-node": "10.9.1", "typedoc": "0.23.10", "typedoc-plugin-markdown": "3.13.4", - "typescript": "4.7.4" + "typescript": "4.7.4", + "eslint-plugin-ethereumjs": "file:./eslint" }, "engines": { "node": ">=14", diff --git a/packages/client/lib/sync/fetcher/accountfetcher.ts b/packages/client/lib/sync/fetcher/accountfetcher.ts index 42112fe865..4aea59c10b 100644 --- a/packages/client/lib/sync/fetcher/accountfetcher.ts +++ b/packages/client/lib/sync/fetcher/accountfetcher.ts @@ -1,6 +1,6 @@ import { Trie } from '@ethereumjs/trie' import { - KECCAK256_NULL_S, + KECCAK256_NULL, KECCAK256_RLP, accountBodyToRLP, bigIntToBytes, @@ -349,14 +349,13 @@ export class AccountFetcher extends Fetcher return } const storageFetchRequests = new Set() - const byteCodeFetchRequests = new Set() + const byteCodeFetchRequests = new Set() for (const account of result) { await this.accountTrie.put(account.hash, accountBodyToRLP(account.body)) // build record of accounts that need storage slots to be fetched - const storageRoot: Uint8Array = - account.body[2] instanceof Uint8Array ? account.body[2] : Uint8Array.from(account.body[2]) - if (!equalsBytes(storageRoot, KECCAK256_RLP)) { + const storageRoot: Uint8Array = account.body[2] + if (equalsBytes(storageRoot, KECCAK256_RLP) === false) { storageFetchRequests.add({ accountHash: account.hash, storageRoot, @@ -365,9 +364,8 @@ export class AccountFetcher extends Fetcher }) } // build record of accounts that need bytecode to be fetched - const codeHash: Buffer = - account.body[3] instanceof Buffer ? account.body[3] : Buffer.from(account.body[3]) - if (codeHash.compare(Buffer.from(KECCAK256_NULL_S, 'hex')) !== 0) { + const codeHash: Uint8Array = account.body[3] + if (!(equalsBytes(codeHash, KECCAK256_NULL) === true)) { byteCodeFetchRequests.add(codeHash) } } @@ -377,7 +375,7 @@ export class AccountFetcher extends Fetcher ) if (byteCodeFetchRequests.size > 0) this.byteCodeFetcher.enqueueByByteCodeRequestList( - Array.from(byteCodeFetchRequests) as Buffer[] + Array.from(byteCodeFetchRequests) as Uint8Array[] ) } diff --git a/packages/client/test/sim/sharding.spec.ts b/packages/client/test/sim/sharding.spec.ts index 59a5a5624f..94d0532628 100644 --- a/packages/client/test/sim/sharding.spec.ts +++ b/packages/client/test/sim/sharding.spec.ts @@ -106,7 +106,7 @@ tape('sharding/eip4844 hardfork tests', async (t) => { 4, 4096, pkey, - '0x' + randomBytes(20).toString('hex'), + bytesToPrefixedHexString(randomBytes(20)), undefined, { common } ) diff --git a/packages/evm/src/precompiles/0a-bls12-g1add.ts b/packages/evm/src/precompiles/0a-bls12-g1add.ts index 1388851876..0aa6fe9faf 100644 --- a/packages/evm/src/precompiles/0a-bls12-g1add.ts +++ b/packages/evm/src/precompiles/0a-bls12-g1add.ts @@ -1,5 +1,5 @@ import { short } from '@ethereumjs/util' -import { equalsBytes } from 'ethereum-cryptography/utils' +import { bytesToHex, equalsBytes } from 'ethereum-cryptography/utils' import { EvmErrorResult, OOGResult } from '../evm' import { ERROR, EvmError } from '../exceptions' @@ -75,7 +75,7 @@ export async function precompile0a(opts: PrecompileInput): Promise { const returnValue = BLS12_381_FromG1Point(result) if (opts._debug !== undefined) { - opts._debug(`BLS12G1ADD (0x0a) return value=${returnValue.toString('hex')}`) + opts._debug(`BLS12G1ADD (0x0a) return value=${bytesToHex(returnValue)}`) } return { diff --git a/packages/evm/src/precompiles/0b-bls12-g1mul.ts b/packages/evm/src/precompiles/0b-bls12-g1mul.ts index b006d88ea1..78d562af56 100644 --- a/packages/evm/src/precompiles/0b-bls12-g1mul.ts +++ b/packages/evm/src/precompiles/0b-bls12-g1mul.ts @@ -1,5 +1,5 @@ import { short } from '@ethereumjs/util' -import { equalsBytes } from 'ethereum-cryptography/utils' +import { bytesToHex, equalsBytes } from 'ethereum-cryptography/utils' import { EvmErrorResult, OOGResult } from '../evm' import { ERROR, EvmError } from '../exceptions' @@ -78,7 +78,7 @@ export async function precompile0b(opts: PrecompileInput): Promise { const returnValue = BLS12_381_FromG1Point(result) if (opts._debug !== undefined) { - opts._debug(`BLS12G1MUL (0x0b) return value=${returnValue.toString('hex')}`) + opts._debug(`BLS12G1MUL (0x0b) return value=${bytesToHex(returnValue)}`) } return { diff --git a/packages/evm/src/precompiles/0c-bls12-g1multiexp.ts b/packages/evm/src/precompiles/0c-bls12-g1multiexp.ts index 884b23d6a1..878200f405 100644 --- a/packages/evm/src/precompiles/0c-bls12-g1multiexp.ts +++ b/packages/evm/src/precompiles/0c-bls12-g1multiexp.ts @@ -1,5 +1,5 @@ import { short } from '@ethereumjs/util' -import { equalsBytes } from 'ethereum-cryptography/utils' +import { bytesToHex, equalsBytes } from 'ethereum-cryptography/utils' import { EvmErrorResult, OOGResult } from '../evm' import { ERROR, EvmError } from '../exceptions' @@ -115,7 +115,7 @@ export async function precompile0c(opts: PrecompileInput): Promise { const returnValue = BLS12_381_FromG1Point(result) if (opts._debug !== undefined) { - opts._debug(`BLS12MULTIEXP (0x0c) return value=${returnValue.toString('hex')}`) + opts._debug(`BLS12MULTIEXP (0x0c) return value=${bytesToHex(returnValue)}`) } return { diff --git a/packages/evm/src/precompiles/0d-bls12-g2add.ts b/packages/evm/src/precompiles/0d-bls12-g2add.ts index 620bf61673..bb0c670deb 100644 --- a/packages/evm/src/precompiles/0d-bls12-g2add.ts +++ b/packages/evm/src/precompiles/0d-bls12-g2add.ts @@ -1,5 +1,5 @@ import { short } from '@ethereumjs/util' -import { equalsBytes } from 'ethereum-cryptography/utils' +import { bytesToHex, equalsBytes } from 'ethereum-cryptography/utils' import { EvmErrorResult, OOGResult } from '../evm' import { ERROR, EvmError } from '../exceptions' @@ -79,7 +79,7 @@ export async function precompile0d(opts: PrecompileInput): Promise { const returnValue = BLS12_381_FromG2Point(result) if (opts._debug !== undefined) { - opts._debug(`BLS12G2ADD (0x0d) return value=${returnValue.toString('hex')}`) + opts._debug(`BLS12G2ADD (0x0d) return value=${bytesToHex(returnValue)}`) } return { diff --git a/packages/evm/src/precompiles/0e-bls12-g2mul.ts b/packages/evm/src/precompiles/0e-bls12-g2mul.ts index 546e1964a4..2634fb47b5 100644 --- a/packages/evm/src/precompiles/0e-bls12-g2mul.ts +++ b/packages/evm/src/precompiles/0e-bls12-g2mul.ts @@ -1,5 +1,5 @@ import { short } from '@ethereumjs/util' -import { equalsBytes } from 'ethereum-cryptography/utils' +import { bytesToHex, equalsBytes } from 'ethereum-cryptography/utils' import { EvmErrorResult, OOGResult } from '../evm' import { ERROR, EvmError } from '../exceptions' @@ -81,7 +81,7 @@ export async function precompile0e(opts: PrecompileInput): Promise { const returnValue = BLS12_381_FromG2Point(result) if (opts._debug !== undefined) { - opts._debug(`BLS12G2MUL (0x0e) return value=${returnValue.toString('hex')}`) + opts._debug(`BLS12G2MUL (0x0e) return value=${bytesToHex(returnValue)}`) } return { diff --git a/packages/evm/src/precompiles/0f-bls12-g2multiexp.ts b/packages/evm/src/precompiles/0f-bls12-g2multiexp.ts index d1f4939f2f..63a03fa7a2 100644 --- a/packages/evm/src/precompiles/0f-bls12-g2multiexp.ts +++ b/packages/evm/src/precompiles/0f-bls12-g2multiexp.ts @@ -1,5 +1,5 @@ import { short } from '@ethereumjs/util' -import { equalsBytes } from 'ethereum-cryptography/utils' +import { bytesToHex, equalsBytes } from 'ethereum-cryptography/utils' import { EvmErrorResult, OOGResult } from '../evm' import { ERROR, EvmError } from '../exceptions' @@ -115,7 +115,7 @@ export async function precompile0f(opts: PrecompileInput): Promise { const returnValue = BLS12_381_FromG2Point(result) if (opts._debug !== undefined) { - opts._debug(`BLS12G2MULTIEXP (0x0f) return value=${returnValue.toString('hex')}`) + opts._debug(`BLS12G2MULTIEXP (0x0f) return value=${bytesToHex(returnValue)}`) } return { From 41dfedc64b60817db8b26af31d7e00da6a1913a7 Mon Sep 17 00:00:00 2001 From: Holger Drewes Date: Mon, 17 Apr 2023 13:40:29 +0200 Subject: [PATCH 12/53] Review Integrations for StateManager Cache PR #2630 (#2634) * Client -> RPC: fix return value for not existing account request for eth_getBalance, eth_getTransactionCount * EVM: fix pre-Homestead behavior for contract creation OOG behavior * VM -> EEI: small getExternalBalance() optimization * VM -> VMState: remove comment in generateCanonicalGenesis() * StateManager: storage trie cache optimization * StateManager: loosen account restriction for clearContractStorage() (create empty account if not existing instead of throwing) * StateManager -> Storage Cache: updated internal error message * Some small fixes and optimizations * StateManager code doc fixes * StateManager: run cache tests on both LRU and ORDERED_MAP * vm: fix tests * vm: remove skipped homestead shanghailove test * Apply suggestions from code review Co-authored-by: acolytec3 * EVM: remove commented out code * VM: fix unused import in BlockchainTestRunner --------- Co-authored-by: Jochem Brouwer Co-authored-by: acolytec3 <17355484+acolytec3@users.noreply.github.com> Co-authored-by: acolytec3 --- packages/client/lib/rpc/modules/eth.ts | 4 +- .../client/test/rpc/eth/getBalance.spec.ts | 8 ++ .../test/rpc/eth/getTransactionCount.spec.ts | 8 ++ packages/evm/src/evm.ts | 4 +- packages/evm/src/interpreter.ts | 2 +- packages/statemanager/src/cache/account.ts | 8 +- packages/statemanager/src/cache/storage.ts | 6 +- packages/statemanager/src/stateManager.ts | 14 +- .../statemanager/test/cache/account.spec.ts | 126 +++++++++--------- .../statemanager/test/cache/storage.spec.ts | 124 +++++++++-------- packages/vm/src/eei/eei.ts | 6 +- packages/vm/src/eei/vmState.ts | 4 +- .../tester/runners/BlockchainTestsRunner.ts | 9 +- .../tester/runners/GeneralStateTestsRunner.ts | 4 +- 14 files changed, 173 insertions(+), 154 deletions(-) diff --git a/packages/client/lib/rpc/modules/eth.ts b/packages/client/lib/rpc/modules/eth.ts index 37c2695433..5db2cec8c2 100644 --- a/packages/client/lib/rpc/modules/eth.ts +++ b/packages/client/lib/rpc/modules/eth.ts @@ -529,7 +529,7 @@ export class Eth { await vm.stateManager.setStateRoot(block.header.stateRoot) const account = await vm.stateManager.getAccount(address) if (account === undefined) { - throw new Error(`could not read account`) + return '0x0' } return bigIntToHex(account.balance) } @@ -703,7 +703,7 @@ export class Eth { const address = Address.fromString(addressHex) const account = await vm.stateManager.getAccount(address) if (account === undefined) { - throw new Error(`could not read account`) + return '0x0' } return bigIntToHex(account.nonce) } diff --git a/packages/client/test/rpc/eth/getBalance.spec.ts b/packages/client/test/rpc/eth/getBalance.spec.ts index e982d46350..af2ba67209 100644 --- a/packages/client/test/rpc/eth/getBalance.spec.ts +++ b/packages/client/test/rpc/eth/getBalance.spec.ts @@ -81,6 +81,14 @@ tape(`${method}: ensure balance deducts after a tx`, async (t) => { // call with height that exceeds chain height req = params(method, [address.toString(), '0x1']) expectRes = checkError(t, INVALID_PARAMS, 'specified block greater than current height') + await baseRequest(t, server, req, 200, expectRes, false) + + // call with nonexistent account + req = params(method, [`0x${'11'.repeat(20)}`, 'latest']) + expectRes = (res: any) => { + const msg = 'should return 0x0 for nonexistent account' + t.equal(res.body.result, `0x0`, msg) + } await baseRequest(t, server, req, 200, expectRes) }) diff --git a/packages/client/test/rpc/eth/getTransactionCount.spec.ts b/packages/client/test/rpc/eth/getTransactionCount.spec.ts index 52c7fb6d48..e9a4d0fab4 100644 --- a/packages/client/test/rpc/eth/getTransactionCount.spec.ts +++ b/packages/client/test/rpc/eth/getTransactionCount.spec.ts @@ -74,6 +74,14 @@ tape(`${method}: call with valid arguments`, async (t) => { const msg = 'should return the correct nonce (1)' t.equal(res.body.result, '0x1', msg) } + await baseRequest(t, server, req, 200, expectRes, false) + + // call with nonexistent account + req = params(method, [`0x${'11'.repeat(20)}`, 'latest']) + expectRes = (res: any) => { + const msg = 'should return 0x0 for nonexistent account' + t.equal(res.body.result, `0x0`, msg) + } await baseRequest(t, server, req, 200, expectRes) }) diff --git a/packages/evm/src/evm.ts b/packages/evm/src/evm.ts index 6fdf812b40..27fa15e63f 100644 --- a/packages/evm/src/evm.ts +++ b/packages/evm/src/evm.ts @@ -632,10 +632,8 @@ export class EVM implements EVMInterface { // This contract would be considered "DEAD" in later hard forks. // It is thus an unnecessary default item, which we have to save to disk // It does change the state root, but it only wastes storage. - //await this._state.putContractCode(message.to, result.returnValue) - //const account = await this.eei.getAccount(message.to) const account = await this.eei.getAccount(message.to) - await this.eei.putAccount(message.to, account!) + await this.eei.putAccount(message.to, account ?? new Account()) } } diff --git a/packages/evm/src/interpreter.ts b/packages/evm/src/interpreter.ts index e20bec2db8..92dabbedbd 100644 --- a/packages/evm/src/interpreter.ts +++ b/packages/evm/src/interpreter.ts @@ -486,7 +486,7 @@ export class Interpreter { await this._eei.storageStore(this._env.address, key, value) const account = await this._eei.getAccount(this._env.address) if (!account) { - throw new Error('could not read account along persisting memory') + throw new Error('could not read account while persisting memory') } this._env.contract = account } diff --git a/packages/statemanager/src/cache/account.ts b/packages/statemanager/src/cache/account.ts index 1d535b55a6..f2dbb036e0 100644 --- a/packages/statemanager/src/cache/account.ts +++ b/packages/statemanager/src/cache/account.ts @@ -65,8 +65,8 @@ export class AccountCache extends Cache { /** * Puts account to cache under its address. - * @param key - Address of account or undefined if account doesn't exist in the trie - * @param val - Account + * @param address - Address of account + * @param account - Account or undefined if account doesn't exist in the trie */ put(address: Address, account: Account | undefined): void { const addressHex = bytesToHex(address.bytes) @@ -88,7 +88,7 @@ export class AccountCache extends Cache { /** * Returns the queried account or undefined if account doesn't exist - * @param key - Address of account + * @param address - Address of account */ get(address: Address): AccountCacheElement | undefined { const addressHex = bytesToHex(address.bytes) @@ -111,7 +111,7 @@ export class AccountCache extends Cache { /** * Marks address as deleted in cache. - * @param key - Address + * @param address - Address */ del(address: Address): void { const addressHex = bytesToHex(address.bytes) diff --git a/packages/statemanager/src/cache/storage.ts b/packages/statemanager/src/cache/storage.ts index 30e6f335cb..ae7fb70e5b 100644 --- a/packages/statemanager/src/cache/storage.ts +++ b/packages/statemanager/src/cache/storage.ts @@ -124,7 +124,9 @@ export class StorageCache extends Cache { * Returns the queried slot as the RLP encoded storage value * hexStringToBytes('80'): slot is known to be empty * undefined: slot is not in cache - * @param key - Address of account + * @param address - Address of account + * @param key - Storage key + * @returns Storage value or undefined */ get(address: Address, key: Uint8Array): Uint8Array | undefined { const addressHex = bytesToHex(address.bytes) @@ -223,7 +225,7 @@ export class StorageCache extends Cache { itDiffStorage.next() } } else { - throw new Error('Inconsistent cache state') + throw new Error('internal error: storage cache map for account should be defined') } it.next() } diff --git a/packages/statemanager/src/stateManager.ts b/packages/statemanager/src/stateManager.ts index b02ef62305..5d13602888 100644 --- a/packages/statemanager/src/stateManager.ts +++ b/packages/statemanager/src/stateManager.ts @@ -297,8 +297,7 @@ export class DefaultStateManager implements StateManager { } const key = this._prefixCodeHashes ? concatBytes(CODEHASH_PREFIX, codeHash) : codeHash - // @ts-expect-error - await this._trie._db.put(key, value) + await this._trie.database().put(key, value) const keyHex = bytesToHex(key) this._codeCache[keyHex] = value @@ -306,7 +305,7 @@ export class DefaultStateManager implements StateManager { if (this.DEBUG) { this._debug(`Update codeHash (-> ${short(codeHash)}) for account ${address}`) } - if (!(await this.getAccount(address))) { + if ((await this.getAccount(address)) === undefined) { await this.putAccount(address, new Account()) } await this.modifyAccountFields(address, { codeHash }) @@ -334,9 +333,7 @@ export class DefaultStateManager implements StateManager { if (keyHex in this._codeCache) { return this._codeCache[keyHex] } else { - // `db` is a protected member of the `trie` class so telling Typescript to expect this error to avoid casting `db` to `any` - // @ts-expect-error - const code = (await this._trie._db.get(key)) ?? new Uint8Array(0) + const code = (await this._trie.database().get(key)) ?? new Uint8Array(0) this._codeCache[keyHex] = code return code } @@ -355,6 +352,7 @@ export class DefaultStateManager implements StateManager { const storageTrie = this._trie.copy(false) storageTrie.root(account.storageRoot) storageTrie.flushCheckpoints() + this._storageTries[addressHex] = storageTrie return storageTrie } return storageTrie @@ -484,9 +482,9 @@ export class DefaultStateManager implements StateManager { * @param address - Address to clear the storage of */ async clearContractStorage(address: Address): Promise { - const account = await this.getAccount(address) + let account = await this.getAccount(address) if (!account) { - throw new Error(`clearContractStorage() called on non-existing account (${address})`) + account = new Account() } this._storageCache?.clearContractStorage(address) await this._modifyContractStorage(address, account, (storageTrie, done) => { diff --git a/packages/statemanager/test/cache/account.spec.ts b/packages/statemanager/test/cache/account.spec.ts index bd8554f99c..3d44d93b38 100644 --- a/packages/statemanager/test/cache/account.spec.ts +++ b/packages/statemanager/test/cache/account.spec.ts @@ -7,84 +7,90 @@ import { createAccount } from '../util' import type { Account } from '@ethereumjs/util' tape('Account Cache: initialization', (t) => { - t.test('should initialize', async (st) => { - const cache = new AccountCache({ size: 100, type: CacheType.LRU }) + for (const type of [CacheType.LRU, CacheType.ORDERED_MAP]) { + t.test('should initialize', async (st) => { + const cache = new AccountCache({ size: 100, type }) - st.equal(cache._checkpoints, 0, 'initializes given trie') - st.end() - }) + st.equal(cache._checkpoints, 0, 'initializes given trie') + st.end() + }) + } }) tape('Account Cache: put and get account', (t) => { - const cache = new AccountCache({ size: 100, type: CacheType.LRU }) + for (const type of [CacheType.LRU, CacheType.ORDERED_MAP]) { + const cache = new AccountCache({ size: 100, type }) + + const addr = new Address(hexStringToBytes('10'.repeat(20))) + const acc: Account = createAccount(BigInt(1), BigInt(0xff11)) + const accRLP = acc.serialize() + + t.test( + 'should return undefined for CacheElement if account not present in the cache', + async (st) => { + const elem = cache.get(addr) + st.ok(elem === undefined) + st.end() + } + ) + + t.test('should put account', async (st) => { + cache.put(addr, acc) + const elem = cache.get(addr) + st.ok(elem !== undefined && elem.accountRLP && equalsBytes(elem.accountRLP, accRLP)) + st.end() + }) - const addr = new Address(hexStringToBytes('10'.repeat(20))) - const acc: Account = createAccount(BigInt(1), BigInt(0xff11)) - const accRLP = acc.serialize() + t.test('should flush', async (st) => { + const items = cache.flush() + st.equal(items.length, 1) + st.end() + }) + + t.test('should delete account from cache', async (st) => { + cache.del(addr) - t.test( - 'should return undefined for CacheElement if account not present in the cache', - async (st) => { const elem = cache.get(addr) - st.ok(elem === undefined) + st.ok(elem !== undefined && elem.accountRLP === undefined) st.end() - } - ) - - t.test('should put account', async (st) => { - cache.put(addr, acc) - const elem = cache.get(addr) - st.ok(elem !== undefined && elem.accountRLP && equalsBytes(elem.accountRLP, accRLP)) - st.end() - }) - - t.test('should flush', async (st) => { - const items = cache.flush() - st.equal(items.length, 1) - st.end() - }) - - t.test('should delete account from cache', async (st) => { - cache.del(addr) - - const elem = cache.get(addr) - st.ok(elem !== undefined && elem.accountRLP === undefined) - st.end() - }) + }) + } }) tape('Account Cache: checkpointing', (t) => { - const cache = new AccountCache({ size: 100, type: CacheType.LRU }) + for (const type of [CacheType.LRU, CacheType.ORDERED_MAP]) { + const cache = new AccountCache({ size: 100, type }) - const addr = new Address(hexStringToBytes('10'.repeat(20))) - const acc = createAccount(BigInt(1), BigInt(0xff11)) - const accRLP = acc.serialize() + const addr = new Address(hexStringToBytes('10'.repeat(20))) + const acc = createAccount(BigInt(1), BigInt(0xff11)) + const accRLP = acc.serialize() - const updatedAcc = createAccount(BigInt(0x00), BigInt(0xff00)) - const updatedAccRLP = updatedAcc.serialize() + const updatedAcc = createAccount(BigInt(0x00), BigInt(0xff00)) + const updatedAccRLP = updatedAcc.serialize() - t.test('should revert to correct state', async (st) => { - cache.put(addr, acc) - cache.checkpoint() - cache.put(addr, updatedAcc) + t.test('should revert to correct state', async (st) => { + cache.put(addr, acc) + cache.checkpoint() + cache.put(addr, updatedAcc) - let elem = cache.get(addr) - st.ok(elem !== undefined && elem.accountRLP && equalsBytes(elem.accountRLP, updatedAccRLP)) + let elem = cache.get(addr) + st.ok(elem !== undefined && elem.accountRLP && equalsBytes(elem.accountRLP, updatedAccRLP)) - cache.revert() + cache.revert() - elem = cache.get(addr) - st.ok(elem !== undefined && elem.accountRLP && equalsBytes(elem.accountRLP, accRLP)) + elem = cache.get(addr) + st.ok(elem !== undefined && elem.accountRLP && equalsBytes(elem.accountRLP, accRLP)) - st.end() - }) + st.end() + }) - t.test('cache clearing', async (st) => { - const cache = new AccountCache({ size: 100, type: CacheType.LRU }) - cache.put(addr, acc) - cache.clear() - st.equal(cache.size(), 0, 'should delete cache objects with clear=true') + t.test('cache clearing', async (st) => { + const cache = new AccountCache({ size: 100, type: CacheType.LRU }) + cache.put(addr, acc) + cache.clear() + st.equal(cache.size(), 0, 'should delete cache objects with clear=true') - st.end() - }) + st.end() + }) + } }) diff --git a/packages/statemanager/test/cache/storage.spec.ts b/packages/statemanager/test/cache/storage.spec.ts index 1581c75782..f3fa348ff2 100644 --- a/packages/statemanager/test/cache/storage.spec.ts +++ b/packages/statemanager/test/cache/storage.spec.ts @@ -5,83 +5,89 @@ import * as tape from 'tape' import { CacheType, StorageCache } from '../../src/cache' tape('Storage Cache: initialization', (t) => { - t.test('should initialize', async (st) => { - const cache = new StorageCache({ size: 100, type: CacheType.LRU }) + for (const type of [CacheType.LRU, CacheType.ORDERED_MAP]) { + t.test('should initialize', async (st) => { + const cache = new StorageCache({ size: 100, type }) - st.equal(cache._checkpoints, 0, 'initializes given trie') - st.end() - }) + st.equal(cache._checkpoints, 0, 'initializes given trie') + st.end() + }) + } }) tape('Storage Cache: put and get account', (t) => { - const cache = new StorageCache({ size: 100, type: CacheType.LRU }) + for (const type of [CacheType.LRU, CacheType.ORDERED_MAP]) { + const cache = new StorageCache({ size: 100, type }) + + const addr = new Address(hexToBytes('10'.repeat(20))) + const key = hexToBytes('01') + const value = hexToBytes('01') + + t.test( + 'should return undefined for CacheElement if account not present in the cache', + async (st) => { + const elem = cache.get(addr, key) + st.ok(elem === undefined) + st.end() + } + ) + + t.test('should put storage value', async (st) => { + cache.put(addr, key, value) + const elem = cache.get(addr, key) + st.ok(elem !== undefined && equalsBytes(elem, value)) + st.end() + }) - const addr = new Address(hexToBytes('10'.repeat(20))) - const key = hexToBytes('01') - const value = hexToBytes('01') + t.test('should flush', async (st) => { + const items = cache.flush() + st.equal(items.length, 1) + st.end() + }) + + t.test('should delete storage value from cache', async (st) => { + cache.del(addr, key) - t.test( - 'should return undefined for CacheElement if account not present in the cache', - async (st) => { const elem = cache.get(addr, key) - st.ok(elem === undefined) + st.ok(elem !== undefined && equalsBytes(elem, hexToBytes('80'))) st.end() - } - ) - - t.test('should put storage value', async (st) => { - cache.put(addr, key, value) - const elem = cache.get(addr, key) - st.ok(elem !== undefined && equalsBytes(elem, value)) - st.end() - }) - - t.test('should flush', async (st) => { - const items = cache.flush() - st.equal(items.length, 1) - st.end() - }) - - t.test('should delete storage value from cache', async (st) => { - cache.del(addr, key) - - const elem = cache.get(addr, key) - st.ok(elem !== undefined && equalsBytes(elem, hexToBytes('80'))) - st.end() - }) + }) + } }) tape('Storage Cache: checkpointing', (t) => { - const cache = new StorageCache({ size: 100, type: CacheType.LRU }) + for (const type of [CacheType.LRU, CacheType.ORDERED_MAP]) { + const cache = new StorageCache({ size: 100, type }) - const addr = new Address(hexToBytes('10'.repeat(20))) - const key = hexToBytes('01') - const value = hexToBytes('01') + const addr = new Address(hexToBytes('10'.repeat(20))) + const key = hexToBytes('01') + const value = hexToBytes('01') - const updatedValue = hexToBytes('02') + const updatedValue = hexToBytes('02') - t.test('should revert to correct state', async (st) => { - cache.put(addr, key, value) - cache.checkpoint() - cache.put(addr, key, updatedValue) + t.test('should revert to correct state', async (st) => { + cache.put(addr, key, value) + cache.checkpoint() + cache.put(addr, key, updatedValue) - let elem = cache.get(addr, key) - st.ok(elem !== undefined && equalsBytes(elem, updatedValue)) + let elem = cache.get(addr, key) + st.ok(elem !== undefined && equalsBytes(elem, updatedValue)) - cache.revert() + cache.revert() - elem = cache.get(addr, key) - st.ok(elem !== undefined && equalsBytes(elem, value)) + elem = cache.get(addr, key) + st.ok(elem !== undefined && equalsBytes(elem, value)) - st.end() - }) + st.end() + }) - t.test('cache clearing', async (st) => { - const cache = new StorageCache({ size: 100, type: CacheType.LRU }) - cache.put(addr, key, value) - cache.clear() - st.equal(cache.size(), 0, 'should delete cache objects with clear=true') + t.test('cache clearing', async (st) => { + const cache = new StorageCache({ size: 100, type: CacheType.LRU }) + cache.put(addr, key, value) + cache.clear() + st.equal(cache.size(), 0, 'should delete cache objects with clear=true') - st.end() - }) + st.end() + }) + } }) diff --git a/packages/vm/src/eei/eei.ts b/packages/vm/src/eei/eei.ts index b68876418a..f9e6240509 100644 --- a/packages/vm/src/eei/eei.ts +++ b/packages/vm/src/eei/eei.ts @@ -1,4 +1,4 @@ -import { Account, bytesToBigInt } from '@ethereumjs/util' +import { bytesToBigInt } from '@ethereumjs/util' import { VmState } from './vmState' @@ -39,9 +39,9 @@ export class EEI extends VmState implements EEIInterface { * @param address - Address of account */ async getExternalBalance(address: Address): Promise { - let account = await this.getAccount(address) + const account = await this.getAccount(address) if (!account) { - account = new Account() + return BigInt(0) } return account.balance } diff --git a/packages/vm/src/eei/vmState.ts b/packages/vm/src/eei/vmState.ts index 233e11a719..9bc9b9876b 100644 --- a/packages/vm/src/eei/vmState.ts +++ b/packages/vm/src/eei/vmState.ts @@ -266,8 +266,8 @@ export class VmState implements EVMStateAccess { } } await this._stateManager.flush() - // If any empty accounts are put, these should not be marked as touched (when first tx is ran, this account is deleted when it cleans up the accounts) - // TODO: not 100% sure if to keep this line or not along cache refactor rebase, 2023-04-11 + // If any empty accounts are put, these should not be marked as touched + // (when first tx is ran, this account is deleted when it cleans up the accounts) this.touchedJournal.clear() } diff --git a/packages/vm/test/tester/runners/BlockchainTestsRunner.ts b/packages/vm/test/tester/runners/BlockchainTestsRunner.ts index 508e87937f..98cc69a2fd 100644 --- a/packages/vm/test/tester/runners/BlockchainTestsRunner.ts +++ b/packages/vm/test/tester/runners/BlockchainTestsRunner.ts @@ -1,6 +1,6 @@ import { Block } from '@ethereumjs/block' import { Blockchain } from '@ethereumjs/blockchain' -import { ConsensusAlgorithm, Hardfork } from '@ethereumjs/common' +import { ConsensusAlgorithm } from '@ethereumjs/common' import { RLP } from '@ethereumjs/rlp' import { DefaultStateManager } from '@ethereumjs/statemanager' import { Trie } from '@ethereumjs/trie' @@ -25,13 +25,6 @@ function formatBlockHeader(data: any) { } export async function runBlockchainTest(options: any, testData: any, t: tape.Test) { - if ( - options.common.hardfork() === Hardfork.Homestead && - testData._info.source.includes('ShanghaiLove') === true - ) { - t.comment('temporarily skipping ShanghaiLove test on Homestead, see issue 2406') - return - } // ensure that the test data is the right fork data if (testData.network !== options.forkConfigTestSuite) { t.comment(`skipping test: no data available for ${options.forkConfigTestSuite}`) diff --git a/packages/vm/test/tester/runners/GeneralStateTestsRunner.ts b/packages/vm/test/tester/runners/GeneralStateTestsRunner.ts index 91dab4ce31..1dd2912300 100644 --- a/packages/vm/test/tester/runners/GeneralStateTestsRunner.ts +++ b/packages/vm/test/tester/runners/GeneralStateTestsRunner.ts @@ -2,7 +2,7 @@ import { Block } from '@ethereumjs/block' import { Blockchain } from '@ethereumjs/blockchain' import { DefaultStateManager } from '@ethereumjs/statemanager' import { Trie } from '@ethereumjs/trie' -import { Address, bytesToHex, equalsBytes, toBytes } from '@ethereumjs/util' +import { Account, Address, bytesToHex, equalsBytes, toBytes } from '@ethereumjs/util' import { EVM } from '../../../../evm/src' import { EEI } from '../../../src' @@ -104,7 +104,7 @@ async function runTestCase(options: any, testData: any, t: tape.Test) { // Even if no txs are ran, coinbase should always be created const coinbaseAddress = Address.fromString(testData.env.currentCoinbase) const account = await (vm).eei.getAccount(coinbaseAddress) - await (vm).eei.putAccount(coinbaseAddress, account!) + await (vm).eei.putAccount(coinbaseAddress, account ?? new Account()) const stepHandler = (e: InterpreterStep) => { let hexStack = [] From aa56f433bee9677454f89c72db5fd45ddd4d8122 Mon Sep 17 00:00:00 2001 From: g11tech Date: Tue, 18 Apr 2023 15:04:20 +0530 Subject: [PATCH 13/53] client: add proofs to blobsbundle (#2642) --- packages/client/lib/miner/pendingBlock.ts | 5 +++++ packages/client/lib/rpc/modules/engine.ts | 2 ++ packages/client/test/miner/pendingBlock.spec.ts | 10 +++++++++- 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/packages/client/lib/miner/pendingBlock.ts b/packages/client/lib/miner/pendingBlock.ts index 802d354ec6..89bb4bc1a6 100644 --- a/packages/client/lib/miner/pendingBlock.ts +++ b/packages/client/lib/miner/pendingBlock.ts @@ -37,6 +37,7 @@ interface BlobBundle { blockHash: string blobs: Uint8Array[] kzgCommitments: Uint8Array[] + proofs: Uint8Array[] } /** * In the future this class should build a pending block by keeping the @@ -323,10 +324,12 @@ export class PendingBlock { ) => { let blobs: Uint8Array[] = [] let kzgCommitments: Uint8Array[] = [] + let proofs: Uint8Array[] = [] const bundle = this.blobBundles.get(payloadId) if (bundle !== undefined) { blobs = bundle.blobs kzgCommitments = bundle.kzgCommitments + proofs = bundle.proofs } for (let tx of txs) { @@ -334,12 +337,14 @@ export class PendingBlock { if (tx.blobs !== undefined && tx.blobs.length > 0) { blobs = blobs.concat(tx.blobs) kzgCommitments = kzgCommitments.concat(tx.kzgCommitments!) + proofs = proofs.concat(tx.kzgProofs!) } } this.blobBundles.set(payloadId, { blockHash: bytesToPrefixedHexString(blockHash), blobs, kzgCommitments, + proofs, }) } } diff --git a/packages/client/lib/rpc/modules/engine.ts b/packages/client/lib/rpc/modules/engine.ts index a9810b8e38..1621aa5db8 100644 --- a/packages/client/lib/rpc/modules/engine.ts +++ b/packages/client/lib/rpc/modules/engine.ts @@ -112,6 +112,7 @@ type BlobsBundleV1 = { blockHash: string kzgs: Bytes48[] blobs: Blob[] + proofs: Bytes48[] } type ExecutionPayloadBodyV1 = { @@ -1074,6 +1075,7 @@ export class Engine { blockHash: bundle.blockHash, kzgs: bundle.kzgCommitments.map(bytesToPrefixedHexString), blobs: bundle.blobs.map(bytesToPrefixedHexString), + proofs: bundle.proofs.map(bytesToPrefixedHexString), } } diff --git a/packages/client/test/miner/pendingBlock.spec.ts b/packages/client/test/miner/pendingBlock.spec.ts index f86390efc3..1ddd513fff 100644 --- a/packages/client/test/miner/pendingBlock.spec.ts +++ b/packages/client/test/miner/pendingBlock.spec.ts @@ -5,6 +5,7 @@ import { Account, Address, blobsToCommitments, + blobsToProofs, bytesToHex, bytesToPrefixedHexString, commitmentsToVersionedHashes, @@ -277,12 +278,14 @@ tape('[PendingBlock]', async (t) => { const blobs = getBlobs('hello world') const commitments = blobsToCommitments(blobs) const versionedHashes = commitmentsToVersionedHashes(commitments) + const proofs = blobsToProofs(blobs, commitments) const txA01 = BlobEIP4844Transaction.fromTxData( { versionedHashes, blobs, kzgCommitments: commitments, + kzgProofs: proofs, maxFeePerDataGas: 100000000n, gasLimit: 0xffffffn, maxFeePerGas: 1000000000n, @@ -298,8 +301,13 @@ tape('[PendingBlock]', async (t) => { const parentBlock = await vm.blockchain.getCanonicalHeadBlock!() const payloadId = await pendingBlock.start(vm, parentBlock) await pendingBlock.build(payloadId) - const pendingBlob = pendingBlock.blobBundles.get(bytesToPrefixedHexString(payloadId))?.blobs[0] + + const blobBundle = pendingBlock.blobBundles.get(bytesToPrefixedHexString(payloadId))! + st.ok(blobBundle !== undefined) + const pendingBlob = blobBundle.blobs[0] st.ok(pendingBlob !== undefined && equalsBytes(pendingBlob, blobs[0])) + const blobProof = blobBundle.proofs[0] + st.ok(blobProof !== undefined && equalsBytes(blobProof, proofs[0])) st.end() }) t.test('should reset td', (st) => { From 13ceff9e01379c62fa3311db27287f7e66dd2516 Mon Sep 17 00:00:00 2001 From: g11tech Date: Wed, 19 Apr 2023 09:47:34 +0530 Subject: [PATCH 14/53] client: Merge get blobs engine api into getPayloadV3 (#2650) * client: Merge get blobs engine api into getPayloadV3 * some renamings * fix v3 spec * add blobs bundle checks * fix spec --- packages/client/lib/miner/pendingBlock.ts | 61 +++++++------------ packages/client/lib/rpc/modules/engine.ts | 45 ++++---------- .../client/test/miner/pendingBlock.spec.ts | 8 +-- ...sBundleV1.spec.ts => getPayloadV3.spec.ts} | 49 ++++++++++----- ...Payloadv2.spec.ts => newPayloadV2.spec.ts} | 0 ...Payloadv3.spec.ts => newPayloadV3.spec.ts} | 0 6 files changed, 73 insertions(+), 90 deletions(-) rename packages/client/test/rpc/engine/{getBlobsBundleV1.spec.ts => getPayloadV3.spec.ts} (75%) rename packages/client/test/rpc/engine/{newPayloadv2.spec.ts => newPayloadV2.spec.ts} (100%) rename packages/client/test/rpc/engine/{newPayloadv3.spec.ts => newPayloadV3.spec.ts} (100%) diff --git a/packages/client/lib/miner/pendingBlock.ts b/packages/client/lib/miner/pendingBlock.ts index 89bb4bc1a6..408ea1d800 100644 --- a/packages/client/lib/miner/pendingBlock.ts +++ b/packages/client/lib/miner/pendingBlock.ts @@ -1,4 +1,3 @@ -import { BlockHeader } from '@ethereumjs/block' import { BlobEIP4844Transaction } from '@ethereumjs/tx' import { TypeOutput, @@ -33,10 +32,9 @@ interface PendingBlockOpts { skipHardForkValidation?: boolean } -interface BlobBundle { - blockHash: string +export interface BlobsBundle { blobs: Uint8Array[] - kzgCommitments: Uint8Array[] + commitments: Uint8Array[] proofs: Uint8Array[] } /** @@ -55,7 +53,7 @@ export class PendingBlock { txPool: TxPool pendingPayloads: Map = new Map() - blobBundles: Map = new Map() + blobsBundles: Map = new Map() private skipHardForkValidation?: boolean @@ -114,7 +112,7 @@ export class PendingBlock { return payloadIdBytes } - // Prune the builders and blobbundles + // Prune the builders and blobsbundles this.pruneSetToMax(MAX_PAYLOAD_CACHE) if (typeof vm.blockchain.getTotalDifficulty !== 'function') { @@ -191,20 +189,7 @@ export class PendingBlock { // Construct initial blobs bundle when payload is constructed if (vm._common.isActivatedEIP(4844)) { - const header = BlockHeader.fromHeaderData( - { - ...headerData, - number, - gasLimit, - baseFeePerGas, - excessDataGas, - }, - { - hardforkByTTD: td, - common: vm._common, - } - ) - this.constructBlobsBundle(payloadId, blobTxs, header.hash()) + this.constructBlobsBundle(payloadId, blobTxs) } return payloadIdBytes } @@ -221,7 +206,7 @@ export class PendingBlock { void builder.revert() // Remove from pendingPayloads this.pendingPayloads.delete(payloadId) - this.blobBundles.delete(payloadId) + this.blobsBundles.delete(payloadId) } /** @@ -229,7 +214,7 @@ export class PendingBlock { */ async build( payloadIdBytes: Uint8Array | string - ): Promise { + ): Promise { const payloadId = typeof payloadIdBytes !== 'string' ? bytesToPrefixedHexString(payloadIdBytes) : payloadIdBytes const builder = this.pendingPayloads.get(payloadId) @@ -304,11 +289,11 @@ export class PendingBlock { ) // Construct blobs bundle - if (block._common.isActivatedEIP(4844)) { - this.constructBlobsBundle(payloadId, blobTxs, block.header.hash()) - } + const blobs = block._common.isActivatedEIP(4844) + ? this.constructBlobsBundle(payloadId, blobTxs) + : undefined - return [block, builder.transactionReceipts, builder.minerValue] + return [block, builder.transactionReceipts, builder.minerValue, blobs] } /** @@ -317,18 +302,14 @@ export class PendingBlock { * @param txs an array of {@BlobEIP4844Transaction } transactions * @param blockHash the blockhash of the pending block (computed from the header data provided) */ - private constructBlobsBundle = ( - payloadId: string, - txs: BlobEIP4844Transaction[], - blockHash: Uint8Array - ) => { + private constructBlobsBundle = (payloadId: string, txs: BlobEIP4844Transaction[]) => { let blobs: Uint8Array[] = [] - let kzgCommitments: Uint8Array[] = [] + let commitments: Uint8Array[] = [] let proofs: Uint8Array[] = [] - const bundle = this.blobBundles.get(payloadId) + const bundle = this.blobsBundles.get(payloadId) if (bundle !== undefined) { blobs = bundle.blobs - kzgCommitments = bundle.kzgCommitments + commitments = bundle.commitments proofs = bundle.proofs } @@ -336,15 +317,17 @@ export class PendingBlock { tx = tx as BlobEIP4844Transaction if (tx.blobs !== undefined && tx.blobs.length > 0) { blobs = blobs.concat(tx.blobs) - kzgCommitments = kzgCommitments.concat(tx.kzgCommitments!) + commitments = commitments.concat(tx.kzgCommitments!) proofs = proofs.concat(tx.kzgProofs!) } } - this.blobBundles.set(payloadId, { - blockHash: bytesToPrefixedHexString(blockHash), + + const blobsBundle = { blobs, - kzgCommitments, + commitments, proofs, - }) + } + this.blobsBundles.set(payloadId, blobsBundle) + return blobsBundle } } diff --git a/packages/client/lib/rpc/modules/engine.ts b/packages/client/lib/rpc/modules/engine.ts index 1621aa5db8..d7f42b961b 100644 --- a/packages/client/lib/rpc/modules/engine.ts +++ b/packages/client/lib/rpc/modules/engine.ts @@ -22,6 +22,7 @@ import type { Chain } from '../../blockchain' import type { EthereumClient } from '../../client' import type { Config } from '../../config' import type { VMExecution } from '../../execution' +import type { BlobsBundle } from '../../miner' import type { FullEthereumService } from '../../service' import type { HeaderData } from '@ethereumjs/block' import type { VM } from '@ethereumjs/vm' @@ -109,8 +110,7 @@ type TransitionConfigurationV1 = { } type BlobsBundleV1 = { - blockHash: string - kzgs: Bytes48[] + commitments: Bytes48[] blobs: Blob[] proofs: Bytes48[] } @@ -170,12 +170,19 @@ const payloadAttributesFieldValidatorsV2 = { /** * Formats a block to {@link ExecutionPayloadV1}. */ -export const blockToExecutionPayload = (block: Block, value: bigint) => { +export const blockToExecutionPayload = (block: Block, value: bigint, bundle?: BlobsBundle) => { const blockJson = block.toJSON() const header = blockJson.header! const transactions = block.transactions.map((tx) => bytesToPrefixedHexString(tx.serialize())) ?? [] const withdrawalsArr = blockJson.withdrawals ? { withdrawals: blockJson.withdrawals } : {} + const blobsBundle: BlobsBundleV1 | undefined = bundle + ? { + commitments: bundle.commitments.map(bytesToPrefixedHexString), + blobs: bundle.blobs.map(bytesToPrefixedHexString), + proofs: bundle.proofs.map(bytesToPrefixedHexString), + } + : undefined const executionPayload: ExecutionPayload = { blockNumber: header.number!, @@ -195,7 +202,7 @@ export const blockToExecutionPayload = (block: Block, value: bigint) => { transactions, ...withdrawalsArr, } - return { executionPayload, blockValue: bigIntToHex(value) } + return { executionPayload, blockValue: bigIntToHex(value), blobsBundle } } /** @@ -475,11 +482,6 @@ export class Engine { () => this.connectionManager.updateStatus() ) - this.getBlobsBundleV1 = cmMiddleware( - middleware(this.getBlobsBundleV1.bind(this), 1, [[validators.bytes8]]), - () => this.connectionManager.updateStatus() - ) - this.exchangeCapabilities = cmMiddleware( middleware(this.exchangeCapabilities.bind(this), 0, []), () => this.connectionManager.updateStatus() @@ -1003,9 +1005,9 @@ export class Engine { } // The third arg returned is the minerValue which we will use to // value the block - const [block, receipts, value] = built + const [block, receipts, value, blobs] = built await this.execution.runWithoutSetHead({ block }, receipts) - return blockToExecutionPayload(block, value) + return blockToExecutionPayload(block, value, blobs) } catch (error: any) { if (error === EngineError.UnknownPayload) throw error throw { @@ -1058,27 +1060,6 @@ export class Engine { return { terminalTotalDifficulty, terminalBlockHash, terminalBlockNumber } } - /** - * - * @param params a payloadId for a pending block - * @returns a BlobsBundle consisting of the blockhash, the blobs, and the corresponding kzg commitments - */ - private async getBlobsBundleV1(params: [Bytes8]): Promise { - const payloadId = params[0] - - const bundle = this.pendingBlock.blobBundles.get(payloadId) - if (bundle === undefined) { - throw EngineError.UnknownPayload - } - - return { - blockHash: bundle.blockHash, - kzgs: bundle.kzgCommitments.map(bytesToPrefixedHexString), - blobs: bundle.blobs.map(bytesToPrefixedHexString), - proofs: bundle.proofs.map(bytesToPrefixedHexString), - } - } - /** * Returns a list of engine API endpoints supported by the client */ diff --git a/packages/client/test/miner/pendingBlock.spec.ts b/packages/client/test/miner/pendingBlock.spec.ts index 1ddd513fff..32870e96d4 100644 --- a/packages/client/test/miner/pendingBlock.spec.ts +++ b/packages/client/test/miner/pendingBlock.spec.ts @@ -302,11 +302,11 @@ tape('[PendingBlock]', async (t) => { const payloadId = await pendingBlock.start(vm, parentBlock) await pendingBlock.build(payloadId) - const blobBundle = pendingBlock.blobBundles.get(bytesToPrefixedHexString(payloadId))! - st.ok(blobBundle !== undefined) - const pendingBlob = blobBundle.blobs[0] + const blobsBundles = pendingBlock.blobsBundles.get(bytesToPrefixedHexString(payloadId))! + st.ok(blobsBundles !== undefined) + const pendingBlob = blobsBundles.blobs[0] st.ok(pendingBlob !== undefined && equalsBytes(pendingBlob, blobs[0])) - const blobProof = blobBundle.proofs[0] + const blobProof = blobsBundles.proofs[0] st.ok(blobProof !== undefined && equalsBytes(blobProof, proofs[0])) st.end() }) diff --git a/packages/client/test/rpc/engine/getBlobsBundleV1.spec.ts b/packages/client/test/rpc/engine/getPayloadV3.spec.ts similarity index 75% rename from packages/client/test/rpc/engine/getBlobsBundleV1.spec.ts rename to packages/client/test/rpc/engine/getPayloadV3.spec.ts index b14d981581..0555b7b4e3 100644 --- a/packages/client/test/rpc/engine/getBlobsBundleV1.spec.ts +++ b/packages/client/test/rpc/engine/getPayloadV3.spec.ts @@ -1,7 +1,17 @@ import { Hardfork } from '@ethereumjs/common' import { DefaultStateManager } from '@ethereumjs/statemanager' import { TransactionFactory } from '@ethereumjs/tx' -import { Account, Address, hexStringToBytes, initKZG } from '@ethereumjs/util' +import { + Account, + Address, + blobsToCommitments, + blobsToProofs, + bytesToPrefixedHexString, + commitmentsToVersionedHashes, + getBlobs, + hexStringToBytes, + initKZG, +} from '@ethereumjs/util' import * as kzg from 'c-kzg' import * as tape from 'tape' @@ -26,7 +36,7 @@ const validPayloadAttributes = { const validPayload = [validForkChoiceState, { ...validPayloadAttributes, withdrawals: [] }] initKZG(kzg, __dirname + '/../../../lib/trustedSetups/devnet4.txt') -const method = 'engine_getBlobsBundleV1' +const method = 'engine_getPayloadV3' tape(`${method}: call with invalid payloadId`, async (t) => { const { server } = baseSetup({ engine: true, includeVM: true }) @@ -74,10 +84,19 @@ tape(`${method}: call with known payload`, async (t) => { payloadId = res.body.result.payloadId } await baseRequest(t, server, req, 200, expectRes, false) + + const txBlobs = getBlobs('hello world') + const txCommitments = blobsToCommitments(txBlobs) + const txVersionedHashes = commitmentsToVersionedHashes(txCommitments) + const txProofs = blobsToProofs(txBlobs, txCommitments) + const tx = TransactionFactory.fromTxData( { type: 0x03, - versionedHashes: [], + versionedHashes: txVersionedHashes, + blobs: txBlobs, + kzgCommitments: txCommitments, + kzgProofs: txProofs, maxFeePerDataGas: 1n, maxFeePerGas: 10000000000n, maxPriorityFeePerGas: 100000000n, @@ -90,24 +109,24 @@ tape(`${method}: call with known payload`, async (t) => { await service.txPool.add(tx, true) req = params('engine_getPayloadV3', [payloadId]) expectRes = (res: any) => { + const { executionPayload, blobsBundle } = res.body.result t.equal( - res.body.result.executionPayload.blockHash, - '0x4f3068842f4977e1358719f03868cae636e654eca60cf97a1b5619aa006b7185', + executionPayload.blockHash, + '0x3c599ece59439d2dc938e7a2b5e1c675cf8173b6be654f0a689b96936eba96e2', 'built expected block' ) - } - - await baseRequest(t, server, req, 200, expectRes, false) - req = params(method, [payloadId]) - expectRes = (res: any) => { - t.equal( - res.body.result.blockHash, - '0x4f3068842f4977e1358719f03868cae636e654eca60cf97a1b5619aa006b7185', - 'got expected blockHash' + const { commitments, proofs, blobs } = blobsBundle + t.ok( + commitments.length === proofs.length && commitments.length === blobs.length, + 'equal commitments, proofs and blobs' ) + t.equal(blobs.length, 1, '1 blob should be returned') + t.equal(proofs[0], bytesToPrefixedHexString(txProofs[0]), 'proof should match') + t.equal(commitments[0], bytesToPrefixedHexString(txCommitments[0]), 'commitment should match') + t.equal(blobs[0], bytesToPrefixedHexString(txBlobs[0]), 'blob should match') } + await baseRequest(t, server, req, 200, expectRes, false) - // Restore setStateRoot DefaultStateManager.prototype.setStateRoot = originalSetStateRoot DefaultStateManager.prototype.copy = originalStateManagerCopy }) diff --git a/packages/client/test/rpc/engine/newPayloadv2.spec.ts b/packages/client/test/rpc/engine/newPayloadV2.spec.ts similarity index 100% rename from packages/client/test/rpc/engine/newPayloadv2.spec.ts rename to packages/client/test/rpc/engine/newPayloadV2.spec.ts diff --git a/packages/client/test/rpc/engine/newPayloadv3.spec.ts b/packages/client/test/rpc/engine/newPayloadV3.spec.ts similarity index 100% rename from packages/client/test/rpc/engine/newPayloadv3.spec.ts rename to packages/client/test/rpc/engine/newPayloadV3.spec.ts From 69663cc55a9f14e311e5141a78b902a6a9e6bb69 Mon Sep 17 00:00:00 2001 From: Holger Drewes Date: Wed, 19 Apr 2023 12:08:22 +0200 Subject: [PATCH 15/53] Statemanager: Storage Cache Unknown Slot Fix (#2647) * StateManager -> Storage Cache: fix bug where storage slot was wrongly marked as known-to-be-emtpy in cache instead of unknown * empty --------- Co-authored-by: acolytec3 <17355484+acolytec3@users.noreply.github.com> --- packages/statemanager/src/cache/storage.ts | 3 --- .../statemanager/test/cache/storage.spec.ts | 20 +++++++++++++++++-- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/packages/statemanager/src/cache/storage.ts b/packages/statemanager/src/cache/storage.ts index ae7fb70e5b..602bda650a 100644 --- a/packages/statemanager/src/cache/storage.ts +++ b/packages/statemanager/src/cache/storage.ts @@ -76,9 +76,6 @@ export class StorageCache extends Cache { oldStorage = oldStorageMap.getElementByKey(keyHex) } } - if (oldStorage === undefined) { - oldStorage = hexStringToBytes('80') - } diffStorageMap.setElement(keyHex, oldStorage) this._diffCache[this._checkpoints].setElement(addressHex, diffStorageMap) } diff --git a/packages/statemanager/test/cache/storage.spec.ts b/packages/statemanager/test/cache/storage.spec.ts index f3fa348ff2..82836e6d4c 100644 --- a/packages/statemanager/test/cache/storage.spec.ts +++ b/packages/statemanager/test/cache/storage.spec.ts @@ -57,8 +57,6 @@ tape('Storage Cache: put and get account', (t) => { tape('Storage Cache: checkpointing', (t) => { for (const type of [CacheType.LRU, CacheType.ORDERED_MAP]) { - const cache = new StorageCache({ size: 100, type }) - const addr = new Address(hexToBytes('10'.repeat(20))) const key = hexToBytes('01') const value = hexToBytes('01') @@ -66,6 +64,7 @@ tape('Storage Cache: checkpointing', (t) => { const updatedValue = hexToBytes('02') t.test('should revert to correct state', async (st) => { + const cache = new StorageCache({ size: 100, type }) cache.put(addr, key, value) cache.checkpoint() cache.put(addr, key, updatedValue) @@ -81,6 +80,23 @@ tape('Storage Cache: checkpointing', (t) => { st.end() }) + t.test('should revert to unknown if nonexistent in cache before', async (st) => { + const cache = new StorageCache({ size: 100, type }) + + cache.checkpoint() + cache.put(addr, key, value) + + let elem = cache.get(addr, key) + st.ok(elem !== undefined && equalsBytes(elem, value)) + + cache.revert() + + elem = cache.get(addr, key) + st.ok(elem === undefined) + + st.end() + }) + t.test('cache clearing', async (st) => { const cache = new StorageCache({ size: 100, type: CacheType.LRU }) cache.put(addr, key, value) From 0eda3e7d7b4e2d77f6c559b1646eaf6b3b0b953a Mon Sep 17 00:00:00 2001 From: Holger Drewes Date: Wed, 19 Apr 2023 18:01:56 +0200 Subject: [PATCH 16/53] Statemanager: Expand Checkpointing Tests (#2651) * StateManager: expanded account checkpointing tests with various undefined cases * StateManager: extend storage checkpointing test setup, integrate storage root check * StateManager: add different empty/non-empty storage slot scenarios to storage checkpointing tests * StateManager: additional storage checkpointing test cases --- .../test/checkpointing.account.spec.ts | 555 ++++++++++-------- .../test/checkpointing.storage.spec.ts | 529 ++++++++++------- 2 files changed, 631 insertions(+), 453 deletions(-) diff --git a/packages/statemanager/test/checkpointing.account.spec.ts b/packages/statemanager/test/checkpointing.account.spec.ts index 53b4828c63..8ec6a9bb9f 100644 --- a/packages/statemanager/test/checkpointing.account.spec.ts +++ b/packages/statemanager/test/checkpointing.account.spec.ts @@ -3,308 +3,401 @@ import * as tape from 'tape' import { DefaultStateManager } from '../src' +/** + * Compares account read to none or undefined + */ +const accountEval = async ( + sm: DefaultStateManager, + address: Address, + compare: bigint | undefined +) => { + const account = await sm.getAccount(address) + if (compare === undefined) { + return account === undefined + } else { + if (account === undefined) { + return false + } else { + return account.nonce === compare + } + } +} + +type CompareList = [Account | undefined, bigint | undefined] + tape('StateManager -> Account Checkpointing', (t) => { const address = new Address(hexStringToBytes('11'.repeat(20))) - const account = Account.fromAccountData({ - nonce: 1, - }) - const account2 = Account.fromAccountData({ - nonce: 2, - }) - const account3 = Account.fromAccountData({ - nonce: 3, - }) - const account4 = Account.fromAccountData({ - nonce: 4, - }) - const account5 = Account.fromAccountData({ - nonce: 5, - }) - - t.test('No CP -> A1 -> Flush() (-> A1)', async (st) => { - const sm = new DefaultStateManager() - - await sm.putAccount(address, account) - await sm.flush() - st.equal((await sm.getAccount(address))!.nonce, 1n) - - sm.clearCaches() - st.equal((await sm.getAccount(address))!.nonce, 1n) - - st.end() - }) - - t.test('CP -> A1.1 -> Commit -> Flush() (-> A1.1)', async (st) => { - const sm = new DefaultStateManager() - - await sm.checkpoint() - await sm.putAccount(address, account) - await sm.commit() - await sm.flush() - st.equal((await sm.getAccount(address))!.nonce, 1n) - - sm.clearCaches() - st.equal((await sm.getAccount(address))!.nonce, 1n) - - st.end() - }) - - t.test('CP -> A1.1 -> Revert -> Flush() (-> Undefined)', async (st) => { - const sm = new DefaultStateManager() - - await sm.checkpoint() - await sm.putAccount(address, account) - await sm.revert() - await sm.flush() - st.equal(await sm.getAccount(address), undefined) - - sm.clearCaches() - st.equal(await sm.getAccount(address), undefined) - - st.end() - }) - - t.test('A1.1 -> CP -> Commit -> Flush() (-> A1.1)', async (st) => { - const sm = new DefaultStateManager() - - await sm.putAccount(address, account) - await sm.checkpoint() - await sm.commit() - await sm.flush() - st.equal((await sm.getAccount(address))!.nonce, 1n) - - sm.clearCaches() - st.equal((await sm.getAccount(address))!.nonce, 1n) - - st.end() - }) - - t.test('A1.1 -> CP -> Revert -> Flush() (-> A1.1)', async (st) => { - const sm = new DefaultStateManager() - - await sm.putAccount(address, account) - await sm.checkpoint() - await sm.revert() - await sm.flush() - st.equal((await sm.getAccount(address))!.nonce, 1n) - - sm.clearCaches() - st.equal((await sm.getAccount(address))!.nonce, 1n) - - st.end() - }) - - t.test('A1.1 -> CP -> A1.2 -> Commit -> Flush() (-> A1.2)', async (st) => { - const sm = new DefaultStateManager() - - await sm.putAccount(address, account) - await sm.checkpoint() - await sm.putAccount(address, account2) - await sm.commit() - await sm.flush() - st.equal((await sm.getAccount(address))!.nonce, 2n) - - sm.clearCaches() - st.equal((await sm.getAccount(address))!.nonce, 2n) - - st.end() - }) - - t.test('A1.1 -> CP -> A1.2 -> Commit -> A1.3 -> Flush() (-> A1.3)', async (st) => { - const sm = new DefaultStateManager() - await sm.putAccount(address, account) - await sm.checkpoint() - await sm.putAccount(address, account2) - await sm.commit() - await sm.putAccount(address, account3) - await sm.flush() - st.equal((await sm.getAccount(address))!.nonce, 3n) + const accountN1: CompareList = [ + Account.fromAccountData({ + nonce: 1, + }), + 1n, + ] + const accountN2: CompareList = [ + Account.fromAccountData({ + nonce: 2, + }), + 2n, + ] + const accountN3: CompareList = [ + Account.fromAccountData({ + nonce: 3, + }), + 3n, + ] + const accountN4: CompareList = [ + Account.fromAccountData({ + nonce: 4, + }), + 4n, + ] + const accountN5: CompareList = [ + Account.fromAccountData({ + nonce: 5, + }), + 5n, + ] + const accountUndefined: CompareList = [undefined, undefined] + + const accountSets = [ + { + a1: accountN1, + a2: accountN2, + a3: accountN3, + a4: accountN4, + a5: accountN5, + }, + { + a1: accountUndefined, + a2: accountN2, + a3: accountN3, + a4: accountN4, + a5: accountN5, + }, + { + a1: accountUndefined, + a2: accountN2, + a3: accountUndefined, + a4: accountN4, + a5: accountN5, + }, + { + a1: accountUndefined, + a2: accountN2, + a3: accountN3, + a4: accountUndefined, + a5: accountN5, + }, + { + a1: accountN1, + a2: accountUndefined, + a3: accountN3, + a4: accountUndefined, + a5: accountN5, + }, + { + a1: accountN1, + a2: accountUndefined, + a3: accountN3, + a4: accountN4, + a5: accountUndefined, + }, + { + a1: accountN1, + a2: accountN2, + a3: accountUndefined, + a4: accountN4, + a5: accountUndefined, + }, + ] + + for (const as of accountSets) { + t.test('No CP -> A1 -> Flush() (-> A1)', async (st) => { + const sm = new DefaultStateManager() - sm.clearCaches() - st.equal((await sm.getAccount(address))!.nonce, 3n) + await sm.putAccount(address, as.a1[0]) + await sm.flush() + st.ok(accountEval(sm, address, as.a1[1])) - st.end() - }) + sm.clearCaches() + st.ok(accountEval(sm, address, as.a1[1])) - t.test('A1.1 -> CP -> A1.2 -> A1.3 -> Commit -> Flush() (-> A1.3)', async (st) => { - const sm = new DefaultStateManager() + st.end() + }) - await sm.putAccount(address, account) - await sm.checkpoint() - await sm.putAccount(address, account2) - await sm.putAccount(address, account3) - await sm.commit() - await sm.flush() - st.equal((await sm.getAccount(address))!.nonce, 3n) + t.test('CP -> A1.1 -> Commit -> Flush() (-> A1.1)', async (st) => { + const sm = new DefaultStateManager() - sm.clearCaches() - st.equal((await sm.getAccount(address))!.nonce, 3n) + await sm.checkpoint() + await sm.putAccount(address, as.a1[0]) + await sm.commit() + await sm.flush() + st.ok(accountEval(sm, address, as.a1[1])) - st.end() - }) + sm.clearCaches() + st.ok(accountEval(sm, address, as.a1[1])) - t.test('CP -> A1.1 -> A1.2 -> Commit -> Flush() (-> A1.2)', async (st) => { - const sm = new DefaultStateManager() + st.end() + }) - await sm.checkpoint() - await sm.putAccount(address, account) - await sm.putAccount(address, account2) - await sm.commit() - await sm.flush() - st.equal((await sm.getAccount(address))!.nonce, 2n) + t.test('CP -> A1.1 -> Revert -> Flush() (-> Undefined)', async (st) => { + const sm = new DefaultStateManager() - sm.clearCaches() - st.equal((await sm.getAccount(address))!.nonce, 2n) + await sm.checkpoint() + await sm.putAccount(address, as.a1[0]) + await sm.revert() + await sm.flush() + st.ok(accountEval(sm, address, undefined)) - st.end() - }) + sm.clearCaches() + st.ok(accountEval(sm, address, undefined)) - t.test('CP -> A1.1 -> A1.2 -> Revert -> Flush() (-> Undefined)', async (st) => { - const sm = new DefaultStateManager() + st.end() + }) - await sm.checkpoint() - await sm.putAccount(address, account) + t.test('A1.1 -> CP -> Commit -> Flush() (-> A1.1)', async (st) => { + const sm = new DefaultStateManager() - await sm.putAccount(address, account2) - await sm.revert() - await sm.flush() - st.equal(await sm.getAccount(address), undefined) + await sm.putAccount(address, as.a1[0]) + await sm.checkpoint() + await sm.commit() + await sm.flush() + st.ok(accountEval(sm, address, as.a1[1])) - sm.clearCaches() - st.equal(await sm.getAccount(address), undefined) + sm.clearCaches() + st.ok(accountEval(sm, address, as.a1[1])) - st.end() - }) + st.end() + }) - t.test('A1.1 -> CP -> A1.2 -> Revert -> Flush() (-> A1.1)', async (st) => { - const sm = new DefaultStateManager() + t.test('A1.1 -> CP -> Revert -> Flush() (-> A1.1)', async (st) => { + const sm = new DefaultStateManager() - await sm.putAccount(address, account) - await sm.checkpoint() - await sm.putAccount(address, account2) - await sm.revert() - await sm.flush() - st.equal((await sm.getAccount(address))!.nonce, 1n) + await sm.putAccount(address, as.a1[0]) + await sm.checkpoint() + await sm.revert() + await sm.flush() + st.ok(accountEval(sm, address, as.a1[1])) - sm.clearCaches() - st.equal((await sm.getAccount(address))!.nonce, 1n) + sm.clearCaches() + st.ok(accountEval(sm, address, as.a1[1])) - st.end() - }) + st.end() + }) - t.test( - 'A1.1 -> CP -> A1.2 -> CP -> A1.3 -> Commit -> Commit -> Flush() (-> A1.3)', - async (st) => { + t.test('A1.1 -> CP -> A1.2 -> Commit -> Flush() (-> A1.2)', async (st) => { const sm = new DefaultStateManager() - await sm.putAccount(address, account) - await sm.checkpoint() - await sm.putAccount(address, account2) + await sm.putAccount(address, as.a1[0]) await sm.checkpoint() - await sm.putAccount(address, account3) - await sm.commit() + await sm.putAccount(address, as.a2[0]) await sm.commit() await sm.flush() - st.equal((await sm.getAccount(address))!.nonce, 3n) + st.ok(accountEval(sm, address, as.a2[1])) sm.clearCaches() - st.equal((await sm.getAccount(address))!.nonce, 3n) + st.ok(accountEval(sm, address, as.a2[1])) st.end() - } - ) + }) - t.test( - 'A1.1 -> CP -> A1.2 -> CP -> A1.3 -> Commit -> Revert -> Flush() (-> A1.1)', - async (st) => { + t.test('A1.1 -> CP -> A1.2 -> Commit -> A1.3 -> Flush() (-> A1.3)', async (st) => { const sm = new DefaultStateManager() - await sm.putAccount(address, account) + await sm.putAccount(address, as.a1[0]) await sm.checkpoint() - await sm.putAccount(address, account2) - await sm.checkpoint() - await sm.putAccount(address, account3) + await sm.putAccount(address, as.a2[0]) await sm.commit() - await sm.revert() + await sm.putAccount(address, as.a3[0]) await sm.flush() - st.equal((await sm.getAccount(address))!.nonce, 1n) + st.ok(accountEval(sm, address, as.a3[1])) sm.clearCaches() - st.equal((await sm.getAccount(address))!.nonce, 1n) + st.ok(accountEval(sm, address, as.a3[1])) st.end() - } - ) + }) - t.test( - 'A1.1 -> CP -> A1.2 -> CP -> A1.3 -> Revert -> Commit -> Flush() (-> A1.2)', - async (st) => { + t.test('A1.1 -> CP -> A1.2 -> A1.3 -> Commit -> Flush() (-> A1.3)', async (st) => { const sm = new DefaultStateManager() - await sm.putAccount(address, account) - await sm.checkpoint() - await sm.putAccount(address, account2) + await sm.putAccount(address, as.a1[0]) await sm.checkpoint() - await sm.putAccount(address, account3) - await sm.revert() + await sm.putAccount(address, as.a2[0]) + await sm.putAccount(address, as.a3[0]) await sm.commit() await sm.flush() - st.equal((await sm.getAccount(address))!.nonce, 2n) + st.ok(accountEval(sm, address, as.a3[1])) sm.clearCaches() - st.equal((await sm.getAccount(address))!.nonce, 2n) + st.ok(accountEval(sm, address, as.a3[1])) st.end() - } - ) + }) - t.test( - 'A1.1 -> CP -> A1.2 -> CP -> A1.3 -> Revert -> A1.4 -> Commit -> Flush() (-> A1.4)', - async (st) => { + t.test('CP -> A1.1 -> A1.2 -> Commit -> Flush() (-> A1.2)', async (st) => { const sm = new DefaultStateManager() - await sm.putAccount(address, account) await sm.checkpoint() - await sm.putAccount(address, account2) - await sm.checkpoint() - await sm.putAccount(address, account3) - await sm.revert() - await sm.putAccount(address, account4) + await sm.putAccount(address, as.a1[0]) + await sm.putAccount(address, as.a2[0]) await sm.commit() await sm.flush() - st.equal((await sm.getAccount(address))!.nonce, 4n) + st.ok(accountEval(sm, address, as.a2[1])) sm.clearCaches() - st.equal((await sm.getAccount(address))!.nonce, 4n) + st.ok(accountEval(sm, address, as.a2[1])) st.end() - } - ) + }) - t.test( - 'A1.1 -> CP -> A1.2 -> CP -> A1.3 -> Revert -> A1.4 -> CP -> A1.5 -> Commit -> Commit -> Flush() (-> A1.5)', - async (st) => { + t.test('CP -> A1.1 -> A1.2 -> Revert -> Flush() (-> Undefined)', async (st) => { const sm = new DefaultStateManager() - await sm.putAccount(address, account) await sm.checkpoint() - await sm.putAccount(address, account2) - await sm.checkpoint() - await sm.putAccount(address, account3) + await sm.putAccount(address, as.a1[0]) + + await sm.putAccount(address, as.a2[0]) await sm.revert() - await sm.putAccount(address, account4) + await sm.flush() + st.ok(accountEval(sm, address, undefined)) + + sm.clearCaches() + st.ok(accountEval(sm, address, undefined)) + + st.end() + }) + + t.test('A1.1 -> CP -> A1.2 -> Revert -> Flush() (-> A1.1)', async (st) => { + const sm = new DefaultStateManager() + + await sm.putAccount(address, as.a1[0]) await sm.checkpoint() - await sm.putAccount(address, account5) - await sm.commit() - await sm.commit() + await sm.putAccount(address, as.a2[0]) + await sm.revert() await sm.flush() - st.equal((await sm.getAccount(address))!.nonce, 5n) + st.ok(accountEval(sm, address, as.a1[1])) sm.clearCaches() - st.equal((await sm.getAccount(address))!.nonce, 5n) + st.ok(accountEval(sm, address, as.a1[1])) st.end() - } - ) + }) + + t.test( + 'A1.1 -> CP -> A1.2 -> CP -> A1.3 -> Commit -> Commit -> Flush() (-> A1.3)', + async (st) => { + const sm = new DefaultStateManager() + + await sm.putAccount(address, as.a1[0]) + await sm.checkpoint() + await sm.putAccount(address, as.a2[0]) + await sm.checkpoint() + await sm.putAccount(address, as.a3[0]) + await sm.commit() + await sm.commit() + await sm.flush() + st.ok(accountEval(sm, address, as.a3[1])) + + sm.clearCaches() + st.ok(accountEval(sm, address, as.a3[1])) + + st.end() + } + ) + + t.test( + 'A1.1 -> CP -> A1.2 -> CP -> A1.3 -> Commit -> Revert -> Flush() (-> A1.1)', + async (st) => { + const sm = new DefaultStateManager() + + await sm.putAccount(address, as.a1[0]) + await sm.checkpoint() + await sm.putAccount(address, as.a2[0]) + await sm.checkpoint() + await sm.putAccount(address, as.a3[0]) + await sm.commit() + await sm.revert() + await sm.flush() + st.ok(accountEval(sm, address, as.a1[1])) + + sm.clearCaches() + st.ok(accountEval(sm, address, as.a1[1])) + + st.end() + } + ) + + t.test( + 'A1.1 -> CP -> A1.2 -> CP -> A1.3 -> Revert -> Commit -> Flush() (-> A1.2)', + async (st) => { + const sm = new DefaultStateManager() + + await sm.putAccount(address, as.a1[0]) + await sm.checkpoint() + await sm.putAccount(address, as.a2[0]) + await sm.checkpoint() + await sm.putAccount(address, as.a3[0]) + await sm.revert() + await sm.commit() + await sm.flush() + st.ok(accountEval(sm, address, as.a2[1])) + + sm.clearCaches() + st.ok(accountEval(sm, address, as.a2[1])) + + st.end() + } + ) + + t.test( + 'A1.1 -> CP -> A1.2 -> CP -> A1.3 -> Revert -> A1.4 -> Commit -> Flush() (-> A1.4)', + async (st) => { + const sm = new DefaultStateManager() + + await sm.putAccount(address, as.a1[0]) + await sm.checkpoint() + await sm.putAccount(address, as.a2[0]) + await sm.checkpoint() + await sm.putAccount(address, as.a3[0]) + await sm.revert() + await sm.putAccount(address, as.a4[0]) + await sm.commit() + await sm.flush() + st.ok(accountEval(sm, address, as.a4[1])) + + sm.clearCaches() + st.ok(accountEval(sm, address, as.a4[1])) + + st.end() + } + ) + + t.test( + 'A1.1 -> CP -> A1.2 -> CP -> A1.3 -> Revert -> A1.4 -> CP -> A1.5 -> Commit -> Commit -> Flush() (-> A1.5)', + async (st) => { + const sm = new DefaultStateManager() + + await sm.putAccount(address, as.a1[0]) + await sm.checkpoint() + await sm.putAccount(address, as.a2[0]) + await sm.checkpoint() + await sm.putAccount(address, as.a3[0]) + await sm.revert() + await sm.putAccount(address, as.a4[0]) + await sm.checkpoint() + await sm.putAccount(address, as.a5[0]) + await sm.commit() + await sm.commit() + await sm.flush() + st.ok(accountEval(sm, address, as.a5[1])) + + sm.clearCaches() + st.ok(accountEval(sm, address, as.a5[1])) + + st.end() + } + ) + } }) diff --git a/packages/statemanager/test/checkpointing.storage.spec.ts b/packages/statemanager/test/checkpointing.storage.spec.ts index 8f1134b455..0c1f2f6ac4 100644 --- a/packages/statemanager/test/checkpointing.storage.spec.ts +++ b/packages/statemanager/test/checkpointing.storage.spec.ts @@ -3,317 +3,402 @@ import * as tape from 'tape' import { DefaultStateManager } from '../src' +const storageEval = async ( + st: tape.Test, + sm: DefaultStateManager, + address: Address, + key: Uint8Array, + value: Uint8Array, + root: Uint8Array +) => { + st.deepEqual(await sm.getContractStorage(address, key), value, 'storage value should be equal') + const accountCMP = await sm.getAccount(address) + st.deepEqual(accountCMP!.storageRoot, root, 'account storage root should be equal') +} + tape('StateManager -> Storage Checkpointing', (t) => { const address = new Address(hexStringToBytes('11'.repeat(20))) const account = new Account() + const key = hexStringToBytes('01'.repeat(32)) - const value = hexStringToBytes('01') - const value2 = hexStringToBytes('02') - const value3 = hexStringToBytes('03') - const value4 = hexStringToBytes('04') - const value5 = hexStringToBytes('05') - t.test('No CP -> S1 -> Flush() (-> S1)', async (st) => { - const sm = new DefaultStateManager() - await sm.putAccount(address, account) + const value = hexStringToBytes('01') + const root = hexStringToBytes('561a011235f3fe8a4d292eba6d462e09015bbef9f8c3373dd70760bbc86f9a6c') - await sm.putContractStorage(address, key, value) - await sm.flush() - st.deepEqual(await sm.getContractStorage(address, key), value) + const value2 = hexStringToBytes('02') + const root2 = hexStringToBytes('38f95e481a23df7b41934aee346cc960becc5388ad4c67e51f60ac03e8687626') - sm.clearCaches() - st.deepEqual(await sm.getContractStorage(address, key), value) + const value3 = hexStringToBytes('03') + const root3 = hexStringToBytes('dedbee161cad6e3afcc99901dfca9122c16ad48af559d78c4a8b5bec2f5f304b') - st.end() - }) + const value4 = hexStringToBytes('04') + const root4 = hexStringToBytes('e5ccf4afccb012ac0900d0f64f6567a1bceb89f16ff5050da2a64427da94b618') - t.test('CP -> S1.1 -> Commit -> Flush() (-> S1.1)', async (st) => { - const sm = new DefaultStateManager() - await sm.putAccount(address, account) + const value5 = hexStringToBytes('05') + const root5 = hexStringToBytes('b5b5deaf640a41912217f37f6ee338d49c6a476e0912c81188c2954fd1e959f8') - await sm.checkpoint() - await sm.putContractStorage(address, key, value) - await sm.commit() - await sm.flush() - st.deepEqual(await sm.getContractStorage(address, key), value) + const valueEmpty = new Uint8Array(0) + const rootEmpty = hexStringToBytes( + '56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421' + ) - sm.clearCaches() - st.deepEqual(await sm.getContractStorage(address, key), value) + const storageSets = [ + { + s1: { value, root }, + s2: { value: value2, root: root2 }, + s3: { value: value3, root: root3 }, + s4: { value: value4, root: root4 }, + s5: { value: value5, root: root5 }, + }, + { + s1: { value: valueEmpty, root: rootEmpty }, + s2: { value: value2, root: root2 }, + s3: { value: value3, root: root3 }, + s4: { value: value4, root: root4 }, + s5: { value: value5, root: root5 }, + }, + { + s1: { value: valueEmpty, root: rootEmpty }, + s2: { value: value2, root: root2 }, + s3: { value: valueEmpty, root: rootEmpty }, + s4: { value: value4, root: root4 }, + s5: { value: value5, root: root5 }, + }, + { + s1: { value: valueEmpty, root: rootEmpty }, + s2: { value: value2, root: root2 }, + s3: { value: value3, root: root3 }, + s4: { value: valueEmpty, root: rootEmpty }, + s5: { value: value5, root: root5 }, + }, + { + s1: { value, root }, + s2: { value: valueEmpty, root: rootEmpty }, + s3: { value: value3, root: root3 }, + s4: { value: valueEmpty, root: rootEmpty }, + s5: { value: value5, root: root5 }, + }, + { + s1: { value, root }, + s2: { value: valueEmpty, root: rootEmpty }, + s3: { value: value3, root: root3 }, + s4: { value: value4, root: root4 }, + s5: { value: valueEmpty, root: rootEmpty }, + }, + { + s1: { value, root }, + s2: { value: value2, root: root2 }, + s3: { value: valueEmpty, root: rootEmpty }, + s4: { value: value4, root: root4 }, + s5: { value: valueEmpty, root: rootEmpty }, + }, + ] + + for (const s of storageSets) { + t.test('No CP -> S1 -> Flush() (-> S1)', async (st) => { + const sm = new DefaultStateManager() + await sm.putAccount(address, account) - st.end() - }) + await sm.putContractStorage(address, key, s.s1.value) + await sm.flush() + await storageEval(st, sm, address, key, s.s1.value, s.s1.root) - t.test('CP -> S1.1 -> Revert -> Flush() (-> Undefined)', async (st) => { - const sm = new DefaultStateManager() - await sm.putAccount(address, account) + sm.clearCaches() + st.deepEqual(await sm.getContractStorage(address, key), s.s1.value) + await storageEval(st, sm, address, key, s.s1.value, s.s1.root) - await sm.checkpoint() - await sm.putContractStorage(address, key, value) - await sm.revert() - await sm.flush() - st.deepEqual(await sm.getContractStorage(address, key), new Uint8Array(0)) + st.end() + }) - sm.clearCaches() + t.test('CP -> S1.1 -> Commit -> Flush() (-> S1.1)', async (st) => { + const sm = new DefaultStateManager() + await sm.putAccount(address, account) - st.deepEqual(await sm.getContractStorage(address, key), new Uint8Array(0)) + await sm.checkpoint() + await sm.putContractStorage(address, key, s.s1.value) + await sm.commit() + await sm.flush() + await storageEval(st, sm, address, key, s.s1.value, s.s1.root) - st.end() - }) + sm.clearCaches() + await storageEval(st, sm, address, key, s.s1.value, s.s1.root) - t.test('S1.1 -> CP -> Commit -> Flush() (-> S1.1)', async (st) => { - const sm = new DefaultStateManager() - await sm.putAccount(address, account) + st.end() + }) - await sm.putContractStorage(address, key, value) - await sm.checkpoint() - await sm.commit() - await sm.flush() - st.deepEqual(await sm.getContractStorage(address, key), value) + t.test('CP -> S1.1 -> Revert -> Flush() (-> Undefined)', async (st) => { + const sm = new DefaultStateManager() + await sm.putAccount(address, account) - sm.clearCaches() - st.deepEqual(await sm.getContractStorage(address, key), value) + await sm.checkpoint() + await sm.putContractStorage(address, key, s.s1.value) - st.end() - }) + await sm.revert() + await sm.flush() + await storageEval(st, sm, address, key, valueEmpty, rootEmpty) - t.test('S1.1 -> CP -> Revert -> Flush() (-> S1.1)', async (st) => { - const sm = new DefaultStateManager() - await sm.putAccount(address, account) + sm.clearCaches() - await sm.putContractStorage(address, key, value) - await sm.checkpoint() - await sm.revert() - await sm.flush() - st.deepEqual(await sm.getContractStorage(address, key), value) + await storageEval(st, sm, address, key, valueEmpty, rootEmpty) - sm.clearCaches() - st.deepEqual(await sm.getContractStorage(address, key), value) + st.end() + }) - st.end() - }) + t.test('S1.1 -> CP -> Commit -> Flush() (-> S1.1)', async (st) => { + const sm = new DefaultStateManager() + await sm.putAccount(address, account) - t.test('S1.1 -> CP -> S1.2 -> Commit -> Flush() (-> S1.2)', async (st) => { - const sm = new DefaultStateManager() - await sm.putAccount(address, account) + await sm.putContractStorage(address, key, s.s1.value) + await sm.checkpoint() + await sm.commit() + await sm.flush() + await storageEval(st, sm, address, key, s.s1.value, s.s1.root) - await sm.putContractStorage(address, key, value) - await sm.checkpoint() - await sm.putContractStorage(address, key, value2) - await sm.commit() - await sm.flush() - st.deepEqual(await sm.getContractStorage(address, key), value2) + sm.clearCaches() + await storageEval(st, sm, address, key, s.s1.value, s.s1.root) - sm.clearCaches() - st.deepEqual(await sm.getContractStorage(address, key), value2) + st.end() + }) - st.end() - }) + t.test('S1.1 -> CP -> Revert -> Flush() (-> S1.1)', async (st) => { + const sm = new DefaultStateManager() + await sm.putAccount(address, account) - t.test('S1.1 -> CP -> S1.2 -> Commit -> S1.3 -> Flush() (-> S1.3)', async (st) => { - const sm = new DefaultStateManager() - await sm.putAccount(address, account) + await sm.putContractStorage(address, key, s.s1.value) + await sm.checkpoint() + await sm.revert() + await sm.flush() + await storageEval(st, sm, address, key, s.s1.value, s.s1.root) - await sm.putContractStorage(address, key, value) - await sm.checkpoint() - await sm.putContractStorage(address, key, value2) - await sm.commit() - await sm.putContractStorage(address, key, value3) - await sm.flush() - st.deepEqual(await sm.getContractStorage(address, key), value3) + sm.clearCaches() + await storageEval(st, sm, address, key, s.s1.value, s.s1.root) - sm.clearCaches() - st.deepEqual(await sm.getContractStorage(address, key), value3) + st.end() + }) - st.end() - }) + t.test('S1.1 -> CP -> S1.2 -> Commit -> Flush() (-> S1.2)', async (st) => { + const sm = new DefaultStateManager() + await sm.putAccount(address, account) - t.test('S1.1 -> CP -> S1.2 -> S1.3 -> Commit -> Flush() (-> S1.3)', async (st) => { - const sm = new DefaultStateManager() - await sm.putAccount(address, account) + await sm.putContractStorage(address, key, s.s1.value) + await sm.checkpoint() + await sm.putContractStorage(address, key, s.s2.value) + await sm.commit() + await sm.flush() + await storageEval(st, sm, address, key, s.s2.value, s.s2.root) - await sm.putContractStorage(address, key, value) - await sm.checkpoint() - await sm.putContractStorage(address, key, value2) - await sm.putContractStorage(address, key, value3) - await sm.commit() - await sm.flush() - st.deepEqual(await sm.getContractStorage(address, key), value3) + sm.clearCaches() + await storageEval(st, sm, address, key, s.s2.value, s.s2.root) - sm.clearCaches() - st.deepEqual(await sm.getContractStorage(address, key), value3) + st.end() + }) - st.end() - }) - - t.test('CP -> S1.1 -> S1.2 -> Commit -> Flush() (-> S1.2)', async (st) => { - const sm = new DefaultStateManager() - await sm.putAccount(address, account) - - await sm.checkpoint() - await sm.putContractStorage(address, key, value) - await sm.putContractStorage(address, key, value2) - await sm.commit() - await sm.flush() - st.deepEqual((await sm.getContractStorage(address, key))!, value2) - - sm.clearCaches() - st.deepEqual((await sm.getContractStorage(address, key))!, value2) - - st.end() - }) - - t.test('CP -> S1.1 -> S1.2 -> Revert -> Flush() (-> Undefined)', async (st) => { - const sm = new DefaultStateManager() - await sm.putAccount(address, account) - - await sm.checkpoint() - await sm.putContractStorage(address, key, value) - - await sm.putContractStorage(address, key, value2) - await sm.revert() - await sm.flush() - st.deepEqual(await sm.getContractStorage(address, key), new Uint8Array(0)) - - sm.clearCaches() - st.deepEqual(await sm.getContractStorage(address, key), new Uint8Array(0)) - - st.end() - }) - - t.test('S1.1 -> CP -> S1.2 -> Revert -> Flush() (-> S1.1)', async (st) => { - const sm = new DefaultStateManager() - await sm.putAccount(address, account) - - await sm.putContractStorage(address, key, value) - await sm.checkpoint() - await sm.putContractStorage(address, key, value2) - await sm.revert() - await sm.flush() - st.deepEqual(await sm.getContractStorage(address, key), value) - - sm.clearCaches() - st.deepEqual(await sm.getContractStorage(address, key), value) - - st.end() - }) - - t.test( - 'S1.1 -> CP -> S1.2 -> CP -> S1.3 -> Commit -> Commit -> Flush() (-> S1.3)', - async (st) => { + t.test('S1.1 -> CP -> S1.2 -> Commit -> S1.3 -> Flush() (-> S1.3)', async (st) => { const sm = new DefaultStateManager() await sm.putAccount(address, account) - await sm.putContractStorage(address, key, value) - await sm.checkpoint() - await sm.putContractStorage(address, key, value2) + await sm.putContractStorage(address, key, s.s1.value) await sm.checkpoint() - await sm.putContractStorage(address, key, value3) - await sm.commit() + await sm.putContractStorage(address, key, s.s2.value) await sm.commit() + await sm.putContractStorage(address, key, s.s3.value) await sm.flush() - st.deepEqual(await sm.getContractStorage(address, key), value3) + await storageEval(st, sm, address, key, s.s3.value, s.s3.root) sm.clearCaches() - st.deepEqual(await sm.getContractStorage(address, key), value3) + await storageEval(st, sm, address, key, s.s3.value, s.s3.root) st.end() - } - ) + }) - t.test( - 'S1.1 -> CP -> S1.2 -> CP -> S1.3 -> Commit -> Revert -> Flush() (-> S1.1)', - async (st) => { + t.test('S1.1 -> CP -> S1.2 -> S1.3 -> Commit -> Flush() (-> S1.3)', async (st) => { const sm = new DefaultStateManager() await sm.putAccount(address, account) - await sm.putContractStorage(address, key, value) - await sm.checkpoint() - await sm.putContractStorage(address, key, value2) + await sm.putContractStorage(address, key, s.s1.value) await sm.checkpoint() - await sm.putContractStorage(address, key, value3) + await sm.putContractStorage(address, key, s.s2.value) + await sm.putContractStorage(address, key, s.s3.value) await sm.commit() - await sm.revert() await sm.flush() - st.deepEqual(await sm.getContractStorage(address, key), value) + await storageEval(st, sm, address, key, s.s3.value, s.s3.root) sm.clearCaches() - st.deepEqual(await sm.getContractStorage(address, key), value) + await storageEval(st, sm, address, key, s.s3.value, s.s3.root) st.end() - } - ) + }) - t.test( - 'S1.1 -> CP -> S1.2 -> CP -> S1.3 -> Revert -> Commit -> Flush() (-> S1.2)', - async (st) => { + t.test('CP -> S1.1 -> S1.2 -> Commit -> Flush() (-> S1.2)', async (st) => { const sm = new DefaultStateManager() await sm.putAccount(address, account) - await sm.putContractStorage(address, key, value) await sm.checkpoint() - await sm.putContractStorage(address, key, value2) - await sm.checkpoint() - await sm.putContractStorage(address, key, value3) - await sm.revert() + await sm.putContractStorage(address, key, s.s1.value) + await sm.putContractStorage(address, key, s.s2.value) await sm.commit() await sm.flush() - st.deepEqual(await sm.getContractStorage(address, key), value2) + await storageEval(st, sm, address, key, s.s2.value, s.s2.root) sm.clearCaches() - st.deepEqual(await sm.getContractStorage(address, key), value2) + await storageEval(st, sm, address, key, s.s2.value, s.s2.root) st.end() - } - ) + }) - t.test( - 'S1.1 -> CP -> S1.2 -> CP -> S1.3 -> Revert -> S1.4 -> Commit -> Flush() (-> S1.4)', - async (st) => { + t.test('CP -> S1.1 -> S1.2 -> Revert -> Flush() (-> Undefined)', async (st) => { const sm = new DefaultStateManager() await sm.putAccount(address, account) - await sm.putContractStorage(address, key, value) - await sm.checkpoint() - await sm.putContractStorage(address, key, value2) await sm.checkpoint() - await sm.putContractStorage(address, key, value3) + await sm.putContractStorage(address, key, s.s1.value) + + await sm.putContractStorage(address, key, s.s2.value) await sm.revert() - await sm.putContractStorage(address, key, value4) - await sm.commit() await sm.flush() - st.deepEqual(await sm.getContractStorage(address, key), value4) + await storageEval(st, sm, address, key, valueEmpty, rootEmpty) sm.clearCaches() - st.deepEqual(await sm.getContractStorage(address, key), value4) + await storageEval(st, sm, address, key, valueEmpty, rootEmpty) st.end() - } - ) + }) - t.test( - 'S1.1 -> CP -> S1.2 -> CP -> S1.3 -> Revert -> S1.4 -> CP -> S1.5 -> Commit -> Commit -> Flush() (-> S1.5)', - async (st) => { + t.test('S1.1 -> CP -> S1.2 -> Revert -> Flush() (-> S1.1)', async (st) => { const sm = new DefaultStateManager() await sm.putAccount(address, account) - await sm.putContractStorage(address, key, value) - await sm.checkpoint() - await sm.putContractStorage(address, key, value2) + await sm.putContractStorage(address, key, s.s1.value) await sm.checkpoint() - await sm.putContractStorage(address, key, value3) + await sm.putContractStorage(address, key, s.s2.value) await sm.revert() - await sm.putContractStorage(address, key, value4) - await sm.checkpoint() - await sm.putContractStorage(address, key, value5) - await sm.commit() - await sm.commit() await sm.flush() - st.deepEqual(await sm.getContractStorage(address, key), value5) + await storageEval(st, sm, address, key, s.s1.value, s.s1.root) sm.clearCaches() - st.deepEqual(await sm.getContractStorage(address, key), value5) + await storageEval(st, sm, address, key, s.s1.value, s.s1.root) st.end() - } - ) + }) + + t.test( + 'S1.1 -> CP -> S1.2 -> CP -> S1.3 -> Commit -> Commit -> Flush() (-> S1.3)', + async (st) => { + const sm = new DefaultStateManager() + await sm.putAccount(address, account) + + await sm.putContractStorage(address, key, s.s1.value) + await sm.checkpoint() + await sm.putContractStorage(address, key, s.s2.value) + await sm.checkpoint() + await sm.putContractStorage(address, key, s.s3.value) + await sm.commit() + await sm.commit() + await sm.flush() + await storageEval(st, sm, address, key, s.s3.value, s.s3.root) + + sm.clearCaches() + await storageEval(st, sm, address, key, s.s3.value, s.s3.root) + + st.end() + } + ) + + t.test( + 'S1.1 -> CP -> S1.2 -> CP -> S1.3 -> Commit -> Revert -> Flush() (-> S1.1)', + async (st) => { + const sm = new DefaultStateManager() + await sm.putAccount(address, account) + + await sm.putContractStorage(address, key, s.s1.value) + await sm.checkpoint() + await sm.putContractStorage(address, key, s.s2.value) + await sm.checkpoint() + await sm.putContractStorage(address, key, s.s3.value) + await sm.commit() + await sm.revert() + await sm.flush() + await storageEval(st, sm, address, key, s.s1.value, s.s1.root) + + sm.clearCaches() + await storageEval(st, sm, address, key, s.s1.value, s.s1.root) + + st.end() + } + ) + + t.test( + 'S1.1 -> CP -> S1.2 -> CP -> S1.3 -> Revert -> Commit -> Flush() (-> S1.2)', + async (st) => { + const sm = new DefaultStateManager() + await sm.putAccount(address, account) + + await sm.putContractStorage(address, key, s.s1.value) + await sm.checkpoint() + await sm.putContractStorage(address, key, s.s2.value) + await sm.checkpoint() + await sm.putContractStorage(address, key, s.s3.value) + await sm.revert() + await sm.commit() + await sm.flush() + await storageEval(st, sm, address, key, s.s2.value, s.s2.root) + + sm.clearCaches() + await storageEval(st, sm, address, key, s.s2.value, s.s2.root) + + st.end() + } + ) + + t.test( + 'S1.1 -> CP -> S1.2 -> CP -> S1.3 -> Revert -> S1.4 -> Commit -> Flush() (-> S1.4)', + async (st) => { + const sm = new DefaultStateManager() + await sm.putAccount(address, account) + + await sm.putContractStorage(address, key, s.s1.value) + await sm.checkpoint() + await sm.putContractStorage(address, key, s.s2.value) + await sm.checkpoint() + await sm.putContractStorage(address, key, s.s3.value) + await sm.revert() + await sm.putContractStorage(address, key, s.s4.value) + await sm.commit() + await sm.flush() + await storageEval(st, sm, address, key, s.s4.value, s.s4.root) + + sm.clearCaches() + await storageEval(st, sm, address, key, s.s4.value, s.s4.root) + + st.end() + } + ) + + t.test( + 'S1.1 -> CP -> S1.2 -> CP -> S1.3 -> Revert -> S1.4 -> CP -> S1.5 -> Commit -> Commit -> Flush() (-> S1.5)', + async (st) => { + const sm = new DefaultStateManager() + await sm.putAccount(address, account) + + await sm.putContractStorage(address, key, s.s1.value) + await sm.checkpoint() + await sm.putContractStorage(address, key, s.s2.value) + await sm.checkpoint() + await sm.putContractStorage(address, key, s.s3.value) + await sm.revert() + await sm.putContractStorage(address, key, s.s4.value) + await sm.checkpoint() + await sm.putContractStorage(address, key, s.s5.value) + await sm.commit() + await sm.commit() + await sm.flush() + await storageEval(st, sm, address, key, s.s5.value, s.s5.root) + + sm.clearCaches() + await storageEval(st, sm, address, key, s.s5.value, s.s5.root) + + st.end() + } + ) + } }) From 20055286cf8578a34d0fa655179abd98e4b27318 Mon Sep 17 00:00:00 2001 From: g11tech Date: Thu, 20 Apr 2023 15:31:44 +0530 Subject: [PATCH 17/53] common: Rename Merge hardfork to Paris (#2652) * common: Rename Merge hardfork to Paris * fix reference * update tests * further updates * fix test * fix client spec * further updates * fix workflows * fx * fix aliasing --- .github/workflows/vm-pr.yml | 10 +++--- packages/block/test/block.spec.ts | 2 +- packages/block/test/mergeBlock.spec.ts | 2 +- .../block/test/testdata/testnetMerge.json | 2 +- packages/blockchain/test/pos.spec.ts | 4 +-- .../blockchain/test/testdata/testnet.json | 2 +- packages/client/bin/cli.ts | 2 +- packages/client/lib/blockchain/chain.ts | 10 +++--- packages/client/lib/execution/vmexecution.ts | 2 +- packages/client/lib/miner/miner.ts | 2 +- packages/client/lib/net/peerpool.ts | 2 +- .../client/lib/net/protocol/ethprotocol.ts | 2 +- packages/client/lib/rpc/modules/engine.ts | 10 +++--- .../lib/rpc/util/CLConnectionManager.ts | 4 +-- .../client/lib/service/fullethereumservice.ts | 8 ++--- packages/client/lib/sync/fullsync.ts | 10 +++--- packages/client/lib/sync/skeleton.ts | 2 +- packages/client/lib/sync/sync.ts | 4 +-- .../client/test/integration/merge.spec.ts | 4 +-- .../test/integration/mocks/mockchain.ts | 2 +- packages/client/test/miner/miner.spec.ts | 2 +- .../client/test/miner/pendingBlock.spec.ts | 4 +-- .../test/net/protocol/ethprotocol.spec.ts | 2 +- .../rpc/engine/forkchoiceUpdatedV1.spec.ts | 2 +- .../test/service/fullethereumservice.spec.ts | 2 +- packages/common/src/chains/goerli.json | 4 +-- packages/common/src/chains/mainnet.json | 4 +-- packages/common/src/chains/rinkeby.json | 2 +- packages/common/src/chains/ropsten.json | 4 +-- packages/common/src/chains/sepolia.json | 4 +-- packages/common/src/common.ts | 12 +++---- packages/common/src/eips/4844.json | 2 +- packages/common/src/eips/4895.json | 2 +- packages/common/src/enums.ts | 2 +- packages/common/src/hardforks/index.ts | 2 +- .../src/hardforks/{merge.json => paris.json} | 2 +- packages/common/src/utils.ts | 2 +- packages/common/test/chains.spec.ts | 4 +-- .../common/test/data/merge/testnetMerge.json | 2 +- packages/common/test/hardforks.spec.ts | 16 ++++----- packages/common/test/mergePOS.spec.ts | 36 +++++++++---------- packages/common/test/timestamp.spec.ts | 4 +-- packages/common/test/utils.spec.ts | 14 ++++---- packages/evm/src/evm.ts | 2 +- packages/tx/src/baseTransaction.ts | 2 +- packages/tx/test/eip3860.spec.ts | 2 +- packages/vm/src/runTx.ts | 2 +- packages/vm/src/types.ts | 8 ++--- .../EIPs/eip-3670-eof-code-validation.spec.ts | 2 +- ...t-difficulty-opcode-with-prevrando.spec.ts | 2 +- .../api/EIPs/eip-4895-withdrawals.spec.ts | 2 +- packages/vm/test/api/index.spec.ts | 4 +-- packages/vm/test/api/runTx.spec.ts | 6 ++-- .../vm/test/api/testdata/testnetMerge.json | 2 +- .../vm/test/api/tester/tester.config.spec.ts | 2 +- .../test/retesteth/clients/ethereumjs/config | 2 +- .../genesis/correctMiningReward.json | 2 +- packages/vm/test/tester/config.ts | 18 ++++++---- packages/vm/test/util.ts | 2 +- 59 files changed, 140 insertions(+), 136 deletions(-) rename packages/common/src/hardforks/{merge.json => paris.json} (94%) diff --git a/.github/workflows/vm-pr.yml b/.github/workflows/vm-pr.yml index b3813244a0..0ae23ffff5 100644 --- a/.github/workflows/vm-pr.yml +++ b/.github/workflows/vm-pr.yml @@ -44,7 +44,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - fork: ['London', 'Berlin', 'Merge', 'MuirGlacier', 'Istanbul', 'Shanghai'] + fork: ['London', 'Berlin', 'Paris', 'MuirGlacier', 'Istanbul', 'Shanghai'] fail-fast: false steps: - uses: actions/checkout@v3 @@ -69,7 +69,7 @@ jobs: fork: [ 'Shanghai', - 'Merge', + 'Paris', 'London', 'Berlin', 'MuirGlacier', @@ -113,8 +113,8 @@ jobs: '--fork=London --excludeDir=stTimeConsuming', '--fork=Istanbul --dir=GeneralStateTests/stTimeConsuming --expected-test-amount=15561', '--fork=Istanbul --excludeDir=stTimeConsuming --expected-test-amount=19817', - '--fork=Merge --dir=GeneralStateTests/stTimeConsuming', - '--fork=Merge --excludeDir=stTimeConsuming', + '--fork=Paris --dir=GeneralStateTests/stTimeConsuming', + '--fork=Paris --excludeDir=stTimeConsuming', '--fork=ArrowGlacierToMergeAtDiffC0000', '--fork=Shanghai --dir=GeneralStateTests/stTimeConsuming', '--fork=Shanghai --excludeDir=stTimeConsuming', @@ -154,7 +154,7 @@ jobs: '--fork=MuirGlacier --verify-test-amount-alltests', '--fork=Berlin --verify-test-amount-alltests', '--fork=London --verify-test-amount-alltests', - '--fork=Merge --verify-test-amount-alltests', + '--fork=Paris --verify-test-amount-alltests', '--fork=Shanghai --verify-test-amount-alltests', '--fork=ByzantiumToConstantinopleFixAt5 --verify-test-amount-alltests', '--fork=EIP158ToByzantiumAt5 --verify-test-amount-alltests', diff --git a/packages/block/test/block.spec.ts b/packages/block/test/block.spec.ts index 9857da8272..07f6b2c048 100644 --- a/packages/block/test/block.spec.ts +++ b/packages/block/test/block.spec.ts @@ -94,7 +94,7 @@ tape('[Block]: block functions', function (t) { ) st.equal( block._common.hardfork(), - Hardfork.Merge, + Hardfork.Paris, 'should use hardforkByTTD option (td > threshold)' ) diff --git a/packages/block/test/mergeBlock.spec.ts b/packages/block/test/mergeBlock.spec.ts index 3761501ef6..085ac6962b 100644 --- a/packages/block/test/mergeBlock.spec.ts +++ b/packages/block/test/mergeBlock.spec.ts @@ -14,7 +14,7 @@ import { BlockHeader } from '../src/header' const common = new Common({ chain: Chain.Mainnet, - hardfork: Hardfork.Merge, + hardfork: Hardfork.Paris, }) function validateMergeHeader(st: tape.Test, header: BlockHeader) { diff --git a/packages/block/test/testdata/testnetMerge.json b/packages/block/test/testdata/testnetMerge.json index c7ed5626a4..995d7b1d2a 100644 --- a/packages/block/test/testdata/testnetMerge.json +++ b/packages/block/test/testdata/testnetMerge.json @@ -53,7 +53,7 @@ "block": 14 }, { - "name": "merge", + "name": "paris", "block": null, "ttd": "5000" }, diff --git a/packages/blockchain/test/pos.spec.ts b/packages/blockchain/test/pos.spec.ts index af4581efe9..4e2e189e3f 100644 --- a/packages/blockchain/test/pos.spec.ts +++ b/packages/blockchain/test/pos.spec.ts @@ -43,7 +43,7 @@ const buildChain = async (blockchain: Blockchain, common: Common, height: number tape('Proof of Stake - inserting blocks into blockchain', async (t) => { const testnetOnlyTD = JSON.parse(JSON.stringify(testnet)) testnetOnlyTD['hardforks'][11] = { - name: 'merge', + name: 'paris', ttd: BigInt(1313600), block: null, } @@ -76,7 +76,7 @@ tape('Proof of Stake - inserting blocks into blockchain', async (t) => { t.equal( (blockchain as any)._common.hardfork(), - 'merge', + 'paris', 'HF should have been correctly updated' ) const td = await blockchain.getTotalDifficulty(latestHeader.hash()) diff --git a/packages/blockchain/test/testdata/testnet.json b/packages/blockchain/test/testdata/testnet.json index 49370bffcf..177e9b5baa 100644 --- a/packages/blockchain/test/testdata/testnet.json +++ b/packages/blockchain/test/testdata/testnet.json @@ -61,7 +61,7 @@ "block": 10 }, { - "name": "merge", + "name": "paris", "block": 11 } ], diff --git a/packages/client/bin/cli.ts b/packages/client/bin/cli.ts index 8aee7176fe..13435a388a 100755 --- a/packages/client/bin/cli.ts +++ b/packages/client/bin/cli.ts @@ -774,7 +774,7 @@ async function run() { const servers = args.rpc === true || args.rpcEngine === true ? startRPCServers(client, args as RPCArgs) : [] if ( - client.config.chainCommon.gteHardfork(Hardfork.Merge) === true && + client.config.chainCommon.gteHardfork(Hardfork.Paris) === true && (args.rpcEngine === false || args.rpcEngine === undefined) ) { config.logger.warn(`Engine RPC endpoint not activated on a post-Merge HF setup.`) diff --git a/packages/client/lib/blockchain/chain.ts b/packages/client/lib/blockchain/chain.ts index 134293ea87..b26610fee8 100644 --- a/packages/client/lib/blockchain/chain.ts +++ b/packages/client/lib/blockchain/chain.ts @@ -294,16 +294,16 @@ export class Chain { ) // Check and log if this is a terminal block and next block could be merge - if (!this.config.chainCommon.gteHardfork(Hardfork.Merge)) { + if (!this.config.chainCommon.gteHardfork(Hardfork.Paris)) { const nextBlockHf = this.config.chainCommon.getHardforkByBlockNumber( headers.height + BigInt(1), headers.td, undefined ) - if (this.config.chainCommon.hardforkGteHardfork(nextBlockHf, Hardfork.Merge)) { + if (this.config.chainCommon.hardforkGteHardfork(nextBlockHf, Hardfork.Paris)) { this.config.logger.info('*'.repeat(85)) this.config.logger.info( - `Merge hardfork reached 🐼 👉 👈 🐼 ! block=${headers.height} td=${headers.td}` + `Paris (Merge) hardfork reached 🐼 👉 👈 🐼 ! block=${headers.height} td=${headers.td}` ) this.config.logger.info('-'.repeat(85)) this.config.logger.info(' ') @@ -386,7 +386,7 @@ export class Chain { } for (const [i, b] of newBlocks.entries()) { - if (!fromEngine && this.config.chainCommon.gteHardfork(Hardfork.Merge)) { + if (!fromEngine && this.config.chainCommon.gteHardfork(Hardfork.Paris)) { if (i > 0) { // emitOnLast below won't be reached, so run an update here await this.update(!skipUpdateEmit) @@ -443,7 +443,7 @@ export class Chain { let numAdded = 0 for (const [i, h] of headers.entries()) { - if (!mergeIncludes && this.config.chainCommon.gteHardfork(Hardfork.Merge)) { + if (!mergeIncludes && this.config.chainCommon.gteHardfork(Hardfork.Paris)) { if (i > 0) { // emitOnLast below won't be reached, so run an update here await this.update(true) diff --git a/packages/client/lib/execution/vmexecution.ts b/packages/client/lib/execution/vmexecution.ts index 813109c9a9..6e3cddc8a9 100644 --- a/packages/client/lib/execution/vmexecution.ts +++ b/packages/client/lib/execution/vmexecution.ts @@ -443,7 +443,7 @@ export class VMExecution extends Execution { ? `baseFee=${endHeadBlock.header.baseFeePerGas} ` : '' const tdAdd = - this.config.execCommon.gteHardfork(Hardfork.Merge) === true + this.config.execCommon.gteHardfork(Hardfork.Paris) === true ? '' : `td=${this.chain.blocks.td} ` this.config.logger.info( diff --git a/packages/client/lib/miner/miner.ts b/packages/client/lib/miner/miner.ts index edb66401d9..578d55da7c 100644 --- a/packages/client/lib/miner/miner.ts +++ b/packages/client/lib/miner/miner.ts @@ -93,7 +93,7 @@ export class Miner { this.service.chain.headers.td, undefined ) - if (this.config.chainCommon.hardforkGteHardfork(nextBlockHf, Hardfork.Merge)) { + if (this.config.chainCommon.hardforkGteHardfork(nextBlockHf, Hardfork.Paris)) { this.config.logger.info('Miner: reached merge hardfork - stopping') this.stop() return diff --git a/packages/client/lib/net/peerpool.ts b/packages/client/lib/net/peerpool.ts index a8429b0838..f5a2e6aeb1 100644 --- a/packages/client/lib/net/peerpool.ts +++ b/packages/client/lib/net/peerpool.ts @@ -229,7 +229,7 @@ export class PeerPool { */ async _statusCheck() { let NO_PEER_PERIOD_COUNT = 3 - if (this.config.chainCommon.gteHardfork(Hardfork.Merge)) { + if (this.config.chainCommon.gteHardfork(Hardfork.Paris)) { NO_PEER_PERIOD_COUNT = 6 } if (this.size === 0 && this.config.maxPeers > 0) { diff --git a/packages/client/lib/net/protocol/ethprotocol.ts b/packages/client/lib/net/protocol/ethprotocol.ts index 1a63af33d9..b5a00eeb60 100644 --- a/packages/client/lib/net/protocol/ethprotocol.ts +++ b/packages/client/lib/net/protocol/ethprotocol.ts @@ -313,7 +313,7 @@ export class EthProtocol extends Protocol { super(options) this.chain = options.chain - const chainTTD = this.config.chainCommon.hardforkTTD(Hardfork.Merge) + const chainTTD = this.config.chainCommon.hardforkTTD(Hardfork.Paris) if (chainTTD !== null && chainTTD !== undefined) { this.chainTTD = chainTTD } diff --git a/packages/client/lib/rpc/modules/engine.ts b/packages/client/lib/rpc/modules/engine.ts index d7f42b961b..8972ea1278 100644 --- a/packages/client/lib/rpc/modules/engine.ts +++ b/packages/client/lib/rpc/modules/engine.ts @@ -256,7 +256,7 @@ const validBlock = async (hash: Uint8Array, chain: Chain): Promise * Validates that the block satisfies post-merge conditions. */ const validateTerminalBlock = async (block: Block, chain: Chain): Promise => { - const ttd = chain.config.chainCommon.hardforkTTD(Hardfork.Merge) + const ttd = chain.config.chainCommon.hardforkTTD(Hardfork.Paris) if (ttd === null) return false const blockTd = await chain.getTd(block.hash(), block.header.number) @@ -289,7 +289,7 @@ const assembleBlock = async ( const common = config.chainCommon.copy() // This is a post merge block, so set its common accordingly - const ttd = common.hardforkTTD(Hardfork.Merge) + const ttd = common.hardforkTTD(Hardfork.Paris) common.setHardforkByBlockNumber(number, ttd !== null ? ttd : undefined, timestamp) const txs = [] @@ -571,7 +571,7 @@ export class Engine { try { const parent = await this.chain.getBlock(hexStringToBytes(parentHash)) - if (!parent._common.gteHardfork(Hardfork.Merge)) { + if (!parent._common.gteHardfork(Hardfork.Paris)) { const validTerminalBlock = await validateTerminalBlock(parent, this.chain) if (!validTerminalBlock) { const response = { @@ -807,7 +807,7 @@ export class Engine { // Only validate this as terminal block if this block's difficulty is non-zero, // else this is a PoS block but its hardfork could be indeterminable if the skeleton // is not yet connected. - if (!headBlock._common.gteHardfork(Hardfork.Merge) && headBlock.header.difficulty > BigInt(0)) { + if (!headBlock._common.gteHardfork(Hardfork.Paris) && headBlock.header.difficulty > BigInt(0)) { const validTerminalBlock = await validateTerminalBlock(headBlock, this.chain) if (!validTerminalBlock) { const response = { @@ -1040,7 +1040,7 @@ export class Engine { params: [TransitionConfigurationV1] ): Promise { const { terminalTotalDifficulty, terminalBlockHash, terminalBlockNumber } = params[0] - const ttd = this.chain.config.chainCommon.hardforkTTD(Hardfork.Merge) + const ttd = this.chain.config.chainCommon.hardforkTTD(Hardfork.Paris) if (ttd === undefined || ttd === null) { throw { code: INTERNAL_ERROR, diff --git a/packages/client/lib/rpc/util/CLConnectionManager.ts b/packages/client/lib/rpc/util/CLConnectionManager.ts index 47453b85b5..f15964ffa3 100644 --- a/packages/client/lib/rpc/util/CLConnectionManager.ts +++ b/packages/client/lib/rpc/util/CLConnectionManager.ts @@ -282,11 +282,11 @@ export class CLConnectionManager { if ( !this.oneTimeMergeCLConnectionCheck && - this.config.chainCommon.hardfork() === Hardfork.Merge + this.config.chainCommon.hardfork() === Hardfork.Paris ) { if (this.connectionStatus === ConnectionStatus.Disconnected) { this.config.logger.info( - 'Merge HF activated, CL client connection is needed for continued block processing' + 'Paris (Merge) HF activated, CL client connection is needed for continued block processing' ) this.config.logger.info( '(note that CL client might need to be synced up to beacon chain Merge transition slot until communication starts)' diff --git a/packages/client/lib/service/fullethereumservice.ts b/packages/client/lib/service/fullethereumservice.ts index 0c48f37aec..3c76f8c50c 100644 --- a/packages/client/lib/service/fullethereumservice.ts +++ b/packages/client/lib/service/fullethereumservice.ts @@ -67,7 +67,7 @@ export class FullEthereumService extends EthereumService { interval: this.interval, }) } else { - if (this.config.chainCommon.gteHardfork(Hardfork.Merge) === true) { + if (this.config.chainCommon.gteHardfork(Hardfork.Paris) === true) { if (!this.config.disableBeaconSync) { void this.switchToBeaconSync() } @@ -153,7 +153,7 @@ export class FullEthereumService extends EthereumService { } await super.start() this.miner?.start() - if (!this.config.execCommon.gteHardfork(Hardfork.Merge)) { + if (!this.config.execCommon.gteHardfork(Hardfork.Paris)) { void this.execution.run(true, true) } return true @@ -264,7 +264,7 @@ export class FullEthereumService extends EthereumService { break } case 'NewBlockHashes': { - if (this.config.chainCommon.gteHardfork(Hardfork.Merge) === true) { + if (this.config.chainCommon.gteHardfork(Hardfork.Paris) === true) { this.config.logger.debug( `Dropping peer ${peer.id} for sending NewBlockHashes after merge (EIP-3675)` ) @@ -279,7 +279,7 @@ export class FullEthereumService extends EthereumService { break } case 'NewBlock': { - if (this.config.chainCommon.gteHardfork(Hardfork.Merge) === true) { + if (this.config.chainCommon.gteHardfork(Hardfork.Paris) === true) { this.config.logger.debug( `Dropping peer ${peer.id} for sending NewBlock after merge (EIP-3675)` ) diff --git a/packages/client/lib/sync/fullsync.ts b/packages/client/lib/sync/fullsync.ts index 4d3c6cc63e..a76cb77d28 100644 --- a/packages/client/lib/sync/fullsync.ts +++ b/packages/client/lib/sync/fullsync.ts @@ -202,10 +202,10 @@ export class FullSynchronizer extends Synchronizer { * Process blocks fetched from the fetcher. */ async processBlocks(blocks: Block[]) { - if (this.config.chainCommon.gteHardfork(Hardfork.Merge) === true) { + if (this.config.chainCommon.gteHardfork(Hardfork.Paris) === true) { if (this.fetcher !== null) { // If we are beyond the merge block we should stop the fetcher - this.config.logger.info('Merge hardfork reached, stopping block fetcher') + this.config.logger.info('Paris (Merge) hardfork reached, stopping block fetcher') this.clearFetcher() } } @@ -236,13 +236,13 @@ export class FullSynchronizer extends Synchronizer { } else { if ( this.config.chainCommon.hardfork() === Hardfork.MergeForkIdTransition && - this.config.chainCommon.gteHardfork(Hardfork.Merge) === false + this.config.chainCommon.gteHardfork(Hardfork.Paris) === false ) { - const mergeTTD = this.config.chainCommon.hardforkTTD(Hardfork.Merge)! + const mergeTTD = this.config.chainCommon.hardforkTTD(Hardfork.Paris)! const td = this.chain.blocks.td const remaining = mergeTTD - td if (remaining <= mergeTTD / BigInt(10)) { - attentionHF = `Merge HF in ${remaining} TD` + attentionHF = `Paris (Merge) HF in ${remaining} TD` } } } diff --git a/packages/client/lib/sync/skeleton.ts b/packages/client/lib/sync/skeleton.ts index 94a7060d0f..0463db13d4 100644 --- a/packages/client/lib/sync/skeleton.ts +++ b/packages/client/lib/sync/skeleton.ts @@ -93,7 +93,7 @@ export class Skeleton extends MetaDBManager { super(opts) this.status = { progress: { subchains: [] }, linked: false, canonicalHeadReset: true } this.started = 0 - const chainTTD = this.config.chainCommon.hardforkTTD(Hardfork.Merge) + const chainTTD = this.config.chainCommon.hardforkTTD(Hardfork.Paris) if (chainTTD === undefined || chainTTD === null) { throw Error('Cannot create skeleton as merge not set') } diff --git a/packages/client/lib/sync/sync.ts b/packages/client/lib/sync/sync.ts index a593044aad..de842aa3bd 100644 --- a/packages/client/lib/sync/sync.ts +++ b/packages/client/lib/sync/sync.ts @@ -109,7 +109,7 @@ export abstract class Synchronizer { * Start synchronization */ async start(): Promise { - if (this.running || this.config.chainCommon.gteHardfork(Hardfork.Merge) === true) { + if (this.running || this.config.chainCommon.gteHardfork(Hardfork.Paris) === true) { return false } this.running = true @@ -122,7 +122,7 @@ export abstract class Synchronizer { const timeout = setTimeout(() => { this.forceSync = true }, this.interval * 30) - while (this.running && this.config.chainCommon.gteHardfork(Hardfork.Merge) === false) { + while (this.running && this.config.chainCommon.gteHardfork(Hardfork.Paris) === false) { try { await this.sync() } catch (error: any) { diff --git a/packages/client/test/integration/merge.spec.ts b/packages/client/test/integration/merge.spec.ts index 3ef75a7991..c808d2055a 100644 --- a/packages/client/test/integration/merge.spec.ts +++ b/packages/client/test/integration/merge.spec.ts @@ -35,7 +35,7 @@ tape('[Integration:Merge]', async (t) => { { name: 'chainstart', block: 0 }, { name: 'london', block: 0 }, { - name: 'merge', + name: 'paris', block: null, forkHash: null, ttd: BigInt(5), @@ -56,7 +56,7 @@ tape('[Integration:Merge]', async (t) => { { name: 'chainstart', block: 0 }, { name: 'london', block: 0 }, { - name: 'merge', + name: 'paris', block: null, forkHash: null, ttd: BigInt(1000), diff --git a/packages/client/test/integration/mocks/mockchain.ts b/packages/client/test/integration/mocks/mockchain.ts index 5816bcb998..69df38b5a3 100644 --- a/packages/client/test/integration/mocks/mockchain.ts +++ b/packages/client/test/integration/mocks/mockchain.ts @@ -33,7 +33,7 @@ export class MockChain extends Chain { { header: { number: number + 1, - difficulty: common.gteHardfork(Hardfork.Merge) ? 0 : 1, + difficulty: common.gteHardfork(Hardfork.Paris) ? 0 : 1, parentHash: number ? blocks[number - 1].hash() : this.genesis.hash(), }, }, diff --git a/packages/client/test/miner/miner.spec.ts b/packages/client/test/miner/miner.spec.ts index 80a313b4b9..cd77e23e34 100644 --- a/packages/client/test/miner/miner.spec.ts +++ b/packages/client/test/miner/miner.spec.ts @@ -209,7 +209,7 @@ tape('[Miner]', async (t) => { await setBalance(vm, A.address, BigInt('200000000000001')) // add tx - txA011.common.setHardfork(Hardfork.Merge) + txA011.common.setHardfork(Hardfork.Paris) await txPool.add(txA011) t.equal(txPool.txsInPool, 1, 'transaction should be in pool') diff --git a/packages/client/test/miner/pendingBlock.spec.ts b/packages/client/test/miner/pendingBlock.spec.ts index 32870e96d4..ae25ba3bcf 100644 --- a/packages/client/test/miner/pendingBlock.spec.ts +++ b/packages/client/test/miner/pendingBlock.spec.ts @@ -143,7 +143,7 @@ tape('[PendingBlock]', async (t) => { await setBalance(vm, A.address, BigInt(5000000000000000)) await setBalance(vm, B.address, BigInt(5000000000000000)) - txA011.common.setHardfork(Hardfork.Merge) + txA011.common.setHardfork(Hardfork.Paris) await txPool.add(txA011) t.equal(txPool.txsInPool, 1, '1 txA011 should be added') // skip hardfork validation for ease @@ -160,7 +160,7 @@ tape('[PendingBlock]', async (t) => { 'txA011 should be in block' ) - txB011.common.setHardfork(Hardfork.Merge) + txB011.common.setHardfork(Hardfork.Paris) await txPool.add(txB011) t.equal(txPool.txsInPool, 2, '1 txB011 should be added') const built = await pendingBlock.build(payloadId) diff --git a/packages/client/test/net/protocol/ethprotocol.spec.ts b/packages/client/test/net/protocol/ethprotocol.spec.ts index 849650b389..9b36d98bfa 100644 --- a/packages/client/test/net/protocol/ethprotocol.spec.ts +++ b/packages/client/test/net/protocol/ethprotocol.spec.ts @@ -214,7 +214,7 @@ tape('[EthProtocol]', (t) => { transports: [], common: new Common({ chain: Config.CHAIN_DEFAULT, - hardfork: Hardfork.Merge, + hardfork: Hardfork.Paris, eips: [4895, 4844], }), accountCache: 10000, diff --git a/packages/client/test/rpc/engine/forkchoiceUpdatedV1.spec.ts b/packages/client/test/rpc/engine/forkchoiceUpdatedV1.spec.ts index feacb433fb..38a7237780 100644 --- a/packages/client/test/rpc/engine/forkchoiceUpdatedV1.spec.ts +++ b/packages/client/test/rpc/engine/forkchoiceUpdatedV1.spec.ts @@ -31,7 +31,7 @@ const validPayloadAttributes = { suggestedFeeRecipient: '0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b', } -const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Merge }) +const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Paris }) function createBlock(parentBlock: Block) { const prevRandao = crypto.randomBytes(32) diff --git a/packages/client/test/service/fullethereumservice.spec.ts b/packages/client/test/service/fullethereumservice.spec.ts index 4d6cd20bc1..770d679c52 100644 --- a/packages/client/test/service/fullethereumservice.spec.ts +++ b/packages/client/test/service/fullethereumservice.spec.ts @@ -209,7 +209,7 @@ tape('[FullEthereumService]', async (t) => { t.test('should ban peer for sending NewBlock/NewBlockHashes after merge', async (t) => { t.plan(2) - const common = new Common({ chain: 'mainnet', hardfork: Hardfork.Merge }) + const common = new Common({ chain: 'mainnet', hardfork: Hardfork.Paris }) const config = new Config({ common, transports: [], accountCache: 10000, storageCache: 1000 }) const chain = await Chain.create({ config }) const service = new FullEthereumService({ config, chain }) diff --git a/packages/common/src/chains/goerli.json b/packages/common/src/chains/goerli.json index 9e9d3905c3..20650e4b76 100644 --- a/packages/common/src/chains/goerli.json +++ b/packages/common/src/chains/goerli.json @@ -2,7 +2,7 @@ "name": "goerli", "chainId": 5, "networkId": 5, - "defaultHardfork": "merge", + "defaultHardfork": "paris", "consensus": { "type": "poa", "algorithm": "clique", @@ -73,7 +73,7 @@ }, { "//_comment": "The forkHash will remain same as mergeForkIdTransition is post merge, terminal block: https://goerli.etherscan.io/block/7382818", - "name": "merge", + "name": "paris", "ttd": "10790000", "block": 7382819, "forkHash": "0xb8c6299d" diff --git a/packages/common/src/chains/mainnet.json b/packages/common/src/chains/mainnet.json index 79388d8f9f..813cb4cd57 100644 --- a/packages/common/src/chains/mainnet.json +++ b/packages/common/src/chains/mainnet.json @@ -2,7 +2,7 @@ "name": "mainnet", "chainId": 1, "networkId": 1, - "defaultHardfork": "merge", + "defaultHardfork": "paris", "consensus": { "type": "pow", "algorithm": "ethash", @@ -89,7 +89,7 @@ }, { "//_comment": "The forkHash will remain same as mergeForkIdTransition is post merge, terminal block: https://etherscan.io/block/15537393", - "name": "merge", + "name": "paris", "ttd": "58750000000000000000000", "block": 15537394, "forkHash": "0xf0afd0e3" diff --git a/packages/common/src/chains/rinkeby.json b/packages/common/src/chains/rinkeby.json index dcec9a0412..85fae7b120 100644 --- a/packages/common/src/chains/rinkeby.json +++ b/packages/common/src/chains/rinkeby.json @@ -72,7 +72,7 @@ "forkHash": "0x8e29f2f3" }, { - "name": "merge", + "name": "paris", "block": null, "forkHash": null }, diff --git a/packages/common/src/chains/ropsten.json b/packages/common/src/chains/ropsten.json index eae81670b3..7e917d66cd 100644 --- a/packages/common/src/chains/ropsten.json +++ b/packages/common/src/chains/ropsten.json @@ -2,7 +2,7 @@ "name": "ropsten", "chainId": 3, "networkId": 3, - "defaultHardfork": "merge", + "defaultHardfork": "paris", "consensus": { "type": "pow", "algorithm": "ethash", @@ -74,7 +74,7 @@ }, { "//_comment": "The forkHash will remain same as mergeForkIdTransition is post merge", - "name": "merge", + "name": "paris", "ttd": "50000000000000000", "block": null, "forkHash": "0x7119b6b3" diff --git a/packages/common/src/chains/sepolia.json b/packages/common/src/chains/sepolia.json index a88e8b6adb..8c1568ae1f 100644 --- a/packages/common/src/chains/sepolia.json +++ b/packages/common/src/chains/sepolia.json @@ -2,7 +2,7 @@ "name": "sepolia", "chainId": 11155111, "networkId": 11155111, - "defaultHardfork": "merge", + "defaultHardfork": "paris", "consensus": { "type": "pow", "algorithm": "ethash", @@ -75,7 +75,7 @@ }, { "//_comment": "The forkHash will remain same as mergeForkIdTransition is post merge, terminal block: https://sepolia.etherscan.io/block/1450408", - "name": "merge", + "name": "paris", "ttd": "17000000000000000", "block": 1450409, "forkHash": "0xfe3366e7" diff --git a/packages/common/src/common.ts b/packages/common/src/common.ts index 5c690a05e4..b781073c8e 100644 --- a/packages/common/src/common.ts +++ b/packages/common/src/common.ts @@ -235,7 +235,7 @@ export class Common extends EventEmitter { super() this._customChains = opts.customChains ?? [] this._chainParams = this.setChain(opts.chain) - this.DEFAULT_HARDFORK = this._chainParams.defaultHardfork ?? Hardfork.Merge + this.DEFAULT_HARDFORK = this._chainParams.defaultHardfork ?? Hardfork.Paris // Assign hardfork changes in the sequence of the applied hardforks this.HARDFORK_CHANGES = this.hardforks().map((hf) => [ hf.name as HardforkSpecKeys, @@ -739,7 +739,7 @@ export class Common extends EventEmitter { let hfIndex = hfs.findIndex((hf) => hf.name === hardfork) // If the current hardfork is merge, go one behind as merge hf is not part of these // calcs even if the merge hf block is set - if (hardfork === Hardfork.Merge) { + if (hardfork === Hardfork.Paris) { hfIndex -= 1 } // Hardfork not found @@ -758,7 +758,7 @@ export class Common extends EventEmitter { hfTimeOrBlock = hfTimeOrBlock !== null && hfTimeOrBlock !== undefined ? Number(hfTimeOrBlock) : null return ( - hf.name !== Hardfork.Merge && + hf.name !== Hardfork.Paris && hfTimeOrBlock !== null && hfTimeOrBlock !== undefined && hfTimeOrBlock !== currHfTimeOrBlock @@ -788,11 +788,11 @@ export class Common extends EventEmitter { let hfBlock = this.hardforkBlock(hardfork) // If this is a merge hardfork with block not set, then we fallback to previous hardfork // to find the nextHardforkBlock - if (hfBlock === null && hardfork === Hardfork.Merge) { + if (hfBlock === null && hardfork === Hardfork.Paris) { const hfs = this.hardforks() const mergeIndex = hfs.findIndex((hf) => hf.ttd !== null && hf.ttd !== undefined) if (mergeIndex < 0) { - throw Error(`Merge hardfork should have been found`) + throw Error(`Paris (Merge) hardfork should have been found`) } hfBlock = this.hardforkBlock(hfs[mergeIndex - 1].name) } @@ -852,7 +852,7 @@ export class Common extends EventEmitter { typeof blockOrTime === 'number' && blockOrTime !== 0 && blockOrTime !== prevBlockOrTime && - name !== Hardfork.Merge + name !== Hardfork.Paris ) { const hfBlockBytes = hexStringToBytes(blockOrTime.toString(16).padStart(16, '0')) hfBytes = concatBytes(hfBytes, hfBlockBytes) diff --git a/packages/common/src/eips/4844.json b/packages/common/src/eips/4844.json index d078598405..06c92ce750 100644 --- a/packages/common/src/eips/4844.json +++ b/packages/common/src/eips/4844.json @@ -4,7 +4,7 @@ "comment": "Shard Blob Transactions", "url": "https://eips.ethereum.org/EIPS/eip-4844", "status": "Draft", - "minimumHardfork": "merge", + "minimumHardfork": "paris", "requiredEIPs": [1559, 2718, 2930, 4895], "gasConfig": { "dataGasPerBlob": { diff --git a/packages/common/src/eips/4895.json b/packages/common/src/eips/4895.json index 7a9997e982..6967ae1e38 100644 --- a/packages/common/src/eips/4895.json +++ b/packages/common/src/eips/4895.json @@ -4,7 +4,7 @@ "comment": "Beacon chain push withdrawals as operations", "url": "https://eips.ethereum.org/EIPS/eip-4895", "status": "Review", - "minimumHardfork": "merge", + "minimumHardfork": "paris", "requiredEIPs": [], "gasConfig": {}, "gasPrices": {}, diff --git a/packages/common/src/enums.ts b/packages/common/src/enums.ts index a7042290ad..cc1897679b 100644 --- a/packages/common/src/enums.ts +++ b/packages/common/src/enums.ts @@ -22,7 +22,7 @@ export enum Hardfork { ArrowGlacier = 'arrowGlacier', GrayGlacier = 'grayGlacier', MergeForkIdTransition = 'mergeForkIdTransition', - Merge = 'merge', + Paris = 'paris', Shanghai = 'shanghai', ShardingForkDev = 'shardingFork', } diff --git a/packages/common/src/hardforks/index.ts b/packages/common/src/hardforks/index.ts index 9e6216b705..36e1fcb90d 100644 --- a/packages/common/src/hardforks/index.ts +++ b/packages/common/src/hardforks/index.ts @@ -15,6 +15,6 @@ export const hardforks = { arrowGlacier: require('./arrowGlacier.json'), grayGlacier: require('./grayGlacier.json'), mergeForkIdTransition: require('./mergeForkIdTransition.json'), - merge: require('./merge.json'), + paris: require('./paris.json'), shardingFork: require('./sharding.json'), } diff --git a/packages/common/src/hardforks/merge.json b/packages/common/src/hardforks/paris.json similarity index 94% rename from packages/common/src/hardforks/merge.json rename to packages/common/src/hardforks/paris.json index 2c191a49c8..dcb3bdb314 100644 --- a/packages/common/src/hardforks/merge.json +++ b/packages/common/src/hardforks/paris.json @@ -1,5 +1,5 @@ { - "name": "merge", + "name": "paris", "comment": "Hardfork to upgrade the consensus mechanism to Proof-of-Stake", "url": "https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/merge.md", "status": "Final", diff --git a/packages/common/src/utils.ts b/packages/common/src/utils.ts index e427b731de..de41bf2e37 100644 --- a/packages/common/src/utils.ts +++ b/packages/common/src/utils.ts @@ -164,7 +164,7 @@ function parseGethParams(json: any, mergeForkIdPostMerge: boolean = true) { // - Merge hardfork has to be placed just after genesis if any of the genesis hardforks make CL // necessary for e.g. withdrawals const mergeConfig = { - name: Hardfork.Merge, + name: Hardfork.Paris, ttd: config.terminalTotalDifficulty, block: null, } diff --git a/packages/common/test/chains.spec.ts b/packages/common/test/chains.spec.ts index 1f82513a9a..9518d58f39 100644 --- a/packages/common/test/chains.spec.ts +++ b/packages/common/test/chains.spec.ts @@ -8,7 +8,7 @@ tape('[Common/Chains]: Initialization / Chain params', function (t: tape.Test) { st.equal(c.chainName(), 'mainnet', 'should initialize with chain name') st.equal(c.chainId(), BigInt(1), 'should return correct chain Id') st.equal(c.networkId(), BigInt(1), 'should return correct network Id') - st.equal(c.hardfork(), Hardfork.Merge, 'should set hardfork to current default hardfork') + st.equal(c.hardfork(), Hardfork.Paris, 'should set hardfork to current default hardfork') st.equal( c.hardfork(), c.DEFAULT_HARDFORK, @@ -26,7 +26,7 @@ tape('[Common/Chains]: Initialization / Chain params', function (t: tape.Test) { st.equal(c.chainName(), 'mainnet', 'should initialize with chain name') st.equal(c.chainId(), BigInt(1), 'should return correct chain Id') st.equal(c.networkId(), BigInt(1), 'should return correct network Id') - st.equal(c.hardfork(), Hardfork.Merge, 'should set hardfork to current default hardfork') + st.equal(c.hardfork(), Hardfork.Paris, 'should set hardfork to current default hardfork') st.equal( c.hardfork(), c.DEFAULT_HARDFORK, diff --git a/packages/common/test/data/merge/testnetMerge.json b/packages/common/test/data/merge/testnetMerge.json index c7ed5626a4..995d7b1d2a 100644 --- a/packages/common/test/data/merge/testnetMerge.json +++ b/packages/common/test/data/merge/testnetMerge.json @@ -53,7 +53,7 @@ "block": 14 }, { - "name": "merge", + "name": "paris", "block": null, "ttd": "5000" }, diff --git a/packages/common/test/hardforks.spec.ts b/packages/common/test/hardforks.spec.ts index 5841faf6bf..b9ae47b33a 100644 --- a/packages/common/test/hardforks.spec.ts +++ b/packages/common/test/hardforks.spec.ts @@ -20,7 +20,7 @@ tape('[Common]: Hardfork logic', function (t: tape.Test) { Hardfork.ArrowGlacier, Hardfork.GrayGlacier, Hardfork.Shanghai, - Hardfork.Merge, + Hardfork.Paris, ] let c @@ -46,7 +46,7 @@ tape('[Common]: Hardfork logic', function (t: tape.Test) { st.equal(c.getHardforkByBlockNumber(13773000), Hardfork.ArrowGlacier, msg) st.equal(c.getHardforkByBlockNumber(15050000), Hardfork.GrayGlacier, msg) // merge is now specified at 15537394 in config - st.equal(c.getHardforkByBlockNumber(999999999999), Hardfork.Merge, msg) + st.equal(c.getHardforkByBlockNumber(999999999999), Hardfork.Paris, msg) msg = 'should set HF correctly' st.equal(c.setHardforkByBlockNumber(0), Hardfork.Chainstart, msg) @@ -58,7 +58,7 @@ tape('[Common]: Hardfork logic', function (t: tape.Test) { st.equal(c.setHardforkByBlockNumber(13773000), Hardfork.ArrowGlacier, msg) st.equal(c.setHardforkByBlockNumber(15050000), Hardfork.GrayGlacier, msg) // merge is now specified at 15537394 in config - st.equal(c.setHardforkByBlockNumber(999999999999), Hardfork.Merge, msg) + st.equal(c.setHardforkByBlockNumber(999999999999), Hardfork.Paris, msg) c = new Common({ chain: Chain.Ropsten }) st.equal(c.setHardforkByBlockNumber(0), 'tangerineWhistle', msg) @@ -383,7 +383,7 @@ tape('[Common]: Hardfork logic', function (t: tape.Test) { 'should provide the correct initial chain consensus configuration' ) - c = new Common({ chain: Chain.Goerli, hardfork: Hardfork.Merge }) + c = new Common({ chain: Chain.Goerli, hardfork: Hardfork.Paris }) st.equal( c.consensusType(), ConsensusType.ProofOfStake, @@ -408,7 +408,7 @@ tape('[Common]: Hardfork logic', function (t: tape.Test) { let c = new Common({ chain: Chain.Sepolia, hardfork: Hardfork.London }) st.equal( c['HARDFORK_CHANGES'][11][0], - Hardfork.Merge, + Hardfork.Paris, 'should correctly apply hardfork changes' ) st.equal( @@ -423,7 +423,7 @@ tape('[Common]: Hardfork logic', function (t: tape.Test) { ConsensusType.ProofOfWork, 'should provide the correct initial chain consensus type' ) - c.setHardfork(Hardfork.Merge) + c.setHardfork(Hardfork.Paris) st.equal( c.consensusType(), ConsensusType.ProofOfStake, @@ -451,7 +451,7 @@ tape('[Common]: Hardfork logic', function (t: tape.Test) { ) st.equal( c['HARDFORK_CHANGES'][11][0], - Hardfork.Merge, + Hardfork.Paris, 'should correctly apply hardfork changes' ) @@ -462,7 +462,7 @@ tape('[Common]: Hardfork logic', function (t: tape.Test) { ConsensusType.ProofOfWork, 'should provide the correct initial chain consensus type' ) - c.setHardfork(Hardfork.Merge) + c.setHardfork(Hardfork.Paris) st.equal( c.consensusType(), ConsensusType.ProofOfStake, diff --git a/packages/common/test/mergePOS.spec.ts b/packages/common/test/mergePOS.spec.ts index 6ac489353e..401d9535d5 100644 --- a/packages/common/test/mergePOS.spec.ts +++ b/packages/common/test/mergePOS.spec.ts @@ -9,7 +9,7 @@ tape('[Common]: Merge/POS specific logic', function (t: tape.Test) { t.test('hardforkTTD()', function (st: tape.Test) { const customChains = [testnetMerge] const c = new Common({ chain: 'testnetMerge', hardfork: Hardfork.Istanbul, customChains }) - st.equal(c.hardforkTTD(Hardfork.Merge), BigInt(5000), 'should get the HF total difficulty') + st.equal(c.hardforkTTD(Hardfork.Paris), BigInt(5000), 'should get the HF total difficulty') st.equal( c.hardforkTTD('thisHardforkDoesNotExist'), null, @@ -30,9 +30,9 @@ tape('[Common]: Merge/POS specific logic', function (t: tape.Test) { msg = 'block number > last HF block number set, without TD set' st.equal(c.getHardforkByBlockNumber(14), 'london', msg) msg = 'block number > last HF block number set, TD set and equal' - st.equal(c.getHardforkByBlockNumber(15, 5000), 'merge', msg) + st.equal(c.getHardforkByBlockNumber(15, 5000), 'paris', msg) msg = 'block number > last HF block number set, TD set and higher' - st.equal(c.getHardforkByBlockNumber(15, 5001), 'merge', msg) + st.equal(c.getHardforkByBlockNumber(15, 5001), 'paris', msg) msg = 'block number > last HF block number set, TD set and smaller' st.equal(c.getHardforkByBlockNumber(15, 4999), 'london', msg) msg = 'block number < last HF block number set, TD set and smaller' @@ -53,11 +53,11 @@ tape('[Common]: Merge/POS specific logic', function (t: tape.Test) { let msg = 'block number < last HF block number set, without TD set' st.equal(c.getHardforkByBlockNumber(0), 'chainstart', msg) msg = 'block number > last HF block number set, without TD set' - st.equal(c.getHardforkByBlockNumber(16), 'merge', msg) + st.equal(c.getHardforkByBlockNumber(16), 'paris', msg) msg = 'block number > last HF block number set, TD set and equal' - st.equal(c.getHardforkByBlockNumber(16, 5000), 'merge', msg) + st.equal(c.getHardforkByBlockNumber(16, 5000), 'paris', msg) msg = 'block number > last HF block number set, TD set and higher' - st.equal(c.getHardforkByBlockNumber(16, 5001), 'merge', msg) + st.equal(c.getHardforkByBlockNumber(16, 5001), 'paris', msg) msg = 'block number < last HF block number set, TD set and smaller' st.equal(c.getHardforkByBlockNumber(12, 4999), 'berlin', msg) @@ -109,9 +109,9 @@ tape('[Common]: Merge/POS specific logic', function (t: tape.Test) { msg = 'block number > last HF block number set, without TD set' st.equal(c.setHardforkByBlockNumber(14), 'london', msg) msg = 'block number > last HF block number set, TD set and equal' - st.equal(c.setHardforkByBlockNumber(15, 5000), 'merge', msg) + st.equal(c.setHardforkByBlockNumber(15, 5000), 'paris', msg) msg = 'block number > last HF block number set, TD set and higher' - st.equal(c.setHardforkByBlockNumber(15, 5001), 'merge', msg) + st.equal(c.setHardforkByBlockNumber(15, 5001), 'paris', msg) msg = 'block number > last HF block number set, TD set and smaller' st.equal(c.setHardforkByBlockNumber(15, 4999), 'london', msg) msg = 'block number < last HF block number set, TD set and smaller' @@ -132,11 +132,11 @@ tape('[Common]: Merge/POS specific logic', function (t: tape.Test) { let msg = 'block number < last HF block number set, without TD set' st.equal(c.setHardforkByBlockNumber(0), 'chainstart', msg) msg = 'block number > last HF block number set, without TD set' - st.equal(c.setHardforkByBlockNumber(16), 'merge', msg) + st.equal(c.setHardforkByBlockNumber(16), 'paris', msg) msg = 'block number > last HF block number set, TD set and equal' - st.equal(c.setHardforkByBlockNumber(16, 5000), 'merge', msg) + st.equal(c.setHardforkByBlockNumber(16, 5000), 'paris', msg) msg = 'block number > last HF block number set, TD set and higher' - st.equal(c.setHardforkByBlockNumber(16, 5001), 'merge', msg) + st.equal(c.setHardforkByBlockNumber(16, 5001), 'paris', msg) msg = 'block number < last HF block number set, TD set and smaller' st.equal(c.setHardforkByBlockNumber(12, 4999), 'berlin', msg) @@ -206,7 +206,7 @@ tape('[Common]: Merge/POS specific logic', function (t: tape.Test) { const c = Common.fromGethGenesis(json, { chain: 'post-merge' }) const msg = 'should get HF correctly' st.equal(c.getHardforkByBlockNumber(0), Hardfork.London, msg) - st.equal(c.getHardforkByBlockNumber(0, BigInt(0)), Hardfork.Merge, msg) + st.equal(c.getHardforkByBlockNumber(0, BigInt(0)), Hardfork.Paris, msg) }) t.test('test post merge hardforks using Sepolia with block null', function (st: tape.Test) { @@ -222,7 +222,7 @@ tape('[Common]: Merge/POS specific logic', function (t: tape.Test) { // should get Hardfork.London even though happened with 1450408 as terminal as config doesn't have that info st.equal(c.getHardforkByBlockNumber(1450409), Hardfork.London, msg) // however with correct td in input it should select merge - st.equal(c.getHardforkByBlockNumber(1450409, BigInt('17000000000000000')), Hardfork.Merge, msg) + st.equal(c.getHardforkByBlockNumber(1450409, BigInt('17000000000000000')), Hardfork.Paris, msg) // should select MergeForkIdTransition even without td specified as the block is set for this hardfork st.equal(c.getHardforkByBlockNumber(1735371), Hardfork.MergeForkIdTransition, msg) // also with td specified @@ -244,7 +244,7 @@ tape('[Common]: Merge/POS specific logic', function (t: tape.Test) { `should get nextHardforkBlockOrTimestamp correctly` ) st.equal( - c.nextHardforkBlockOrTimestamp(Hardfork.Merge), + c.nextHardforkBlockOrTimestamp(Hardfork.Paris), 1735371n, `should get nextHardforkBlockOrTimestamp correctly` ) @@ -264,7 +264,7 @@ tape('[Common]: Merge/POS specific logic', function (t: tape.Test) { st.equal(c.setHardforkByBlockNumber(0), Hardfork.London, msg) st.equal(c.setHardforkByBlockNumber(1450409), Hardfork.London, msg) - st.equal(c.setHardforkByBlockNumber(1450409, BigInt('17000000000000000')), Hardfork.Merge, msg) + st.equal(c.setHardforkByBlockNumber(1450409, BigInt('17000000000000000')), Hardfork.Paris, msg) st.equal(c.setHardforkByBlockNumber(1735371), Hardfork.MergeForkIdTransition, msg) st.equal( c.setHardforkByBlockNumber(1735371, BigInt('17000000000000000')), @@ -300,10 +300,10 @@ tape('[Common]: Merge/POS specific logic', function (t: tape.Test) { const msg = 'should get HF correctly' // should get merge even without td supplied as the merge hf now has the block specified - st.equal(c.setHardforkByBlockNumber(1450409), Hardfork.Merge, msg) + st.equal(c.setHardforkByBlockNumber(1450409), Hardfork.Paris, msg) st.equal( c.setHardforkByBlockNumber(1450409, BigInt('17000000000000000')), - Hardfork.Merge, + Hardfork.Paris, msg ) st.equal(c.setHardforkByBlockNumber(1735371), Hardfork.MergeForkIdTransition, msg) @@ -320,7 +320,7 @@ tape('[Common]: Merge/POS specific logic', function (t: tape.Test) { `should get nextHardforkBlockOrTimestamp correctly` ) st.equal( - c.nextHardforkBlockOrTimestamp(Hardfork.Merge), + c.nextHardforkBlockOrTimestamp(Hardfork.Paris), 1735371n, `should get nextHardforkBlockOrTimestamp correctly` ) diff --git a/packages/common/test/timestamp.spec.ts b/packages/common/test/timestamp.spec.ts index 510ddf8472..18ccb9a03d 100644 --- a/packages/common/test/timestamp.spec.ts +++ b/packages/common/test/timestamp.spec.ts @@ -80,7 +80,7 @@ tape('[Common]: Timestamp Hardfork logic', function (t: tape.Test) { t.test('forkHash', function (st) { const mainnet = new Common({ chain: Chain.Mainnet }) const hfs = mainnet.hardforks() - const mergeIndex = hfs.findIndex((hf) => hf.name === Hardfork.Merge) + const mergeIndex = hfs.findIndex((hf) => hf.name === Hardfork.Paris) const hardforks = hfs.slice(0, mergeIndex + 1).concat([ // Add these hardforks as specified here: // https://github.com/ethereum/EIPs/pull/6122/files @@ -125,7 +125,7 @@ tape('[Common]: Timestamp Hardfork logic', function (t: tape.Test) { t.test('setForkHashes', function (st) { const mainnet = new Common({ chain: Chain.Mainnet }) const hfs = mainnet.hardforks() - const mergeIndex = hfs.findIndex((hf) => hf.name === Hardfork.Merge) + const mergeIndex = hfs.findIndex((hf) => hf.name === Hardfork.Paris) const hardforks = hfs.slice(0, mergeIndex + 1).concat([ // Add these hardforks as specified here: // https://github.com/ethereum/EIPs/pull/6122/files diff --git a/packages/common/test/utils.spec.ts b/packages/common/test/utils.spec.ts index fd7111c39f..7ff7bd6951 100644 --- a/packages/common/test/utils.spec.ts +++ b/packages/common/test/utils.spec.ts @@ -83,7 +83,7 @@ tape('[Utils/Parse]', (t) => { 'berlin', 'london', 'mergeForkIdTransition', - 'merge', + 'paris', ], 'hardfork parse order should be correct' ) @@ -92,7 +92,7 @@ tape('[Utils/Parse]', (t) => { st.equal(hf.forkHash, kilnForkHashes[hf.name], `${hf.name} forkHash should match`) } - st.equal(common.hardfork(), Hardfork.Merge, 'should correctly infer current hardfork') + st.equal(common.hardfork(), Hardfork.Paris, 'should correctly infer current hardfork') // Ok lets schedule shanghai at block 0, this should force merge to be scheduled at just after // genesis if even mergeForkIdTransition is not confirmed to be post merge @@ -116,7 +116,7 @@ tape('[Utils/Parse]', (t) => { 'istanbul', 'berlin', 'london', - 'merge', + 'paris', 'mergeForkIdTransition', 'shanghai', ], @@ -145,19 +145,19 @@ tape('[Utils/Parse]', (t) => { 'muirGlacier', 'berlin', 'london', - 'merge', + 'paris', 'shanghai', ], 'hardfork parse order should be correct' ) st.equal(common.getHardforkByBlockNumber(0), Hardfork.London, 'london at genesis') - st.equal(common.getHardforkByBlockNumber(1, BigInt(2)), Hardfork.Merge, 'merge at block 1') + st.equal(common.getHardforkByBlockNumber(1, BigInt(2)), Hardfork.Paris, 'merge at block 1') // shanghai is at timestamp 8 st.equal(common.getHardforkByBlockNumber(8), Hardfork.London, 'without timestamp still london') st.equal( common.getHardforkByBlockNumber(8, BigInt(2)), - Hardfork.Merge, + Hardfork.Paris, 'without timestamp at merge' ) st.equal( @@ -197,5 +197,5 @@ const kilnForkHashes: any = { berlin: '0xbcadf543', london: '0xbcadf543', mergeForkIdTransition: '0x013fd1b5', - merge: '0x013fd1b5', + paris: '0x013fd1b5', } diff --git a/packages/evm/src/evm.ts b/packages/evm/src/evm.ts index 27fa15e63f..7454c305dd 100644 --- a/packages/evm/src/evm.ts +++ b/packages/evm/src/evm.ts @@ -165,7 +165,7 @@ export class EVM implements EVMInterface { Hardfork.ArrowGlacier, Hardfork.GrayGlacier, Hardfork.MergeForkIdTransition, - Hardfork.Merge, + Hardfork.Paris, Hardfork.Shanghai, Hardfork.ShardingForkDev, ] diff --git a/packages/tx/src/baseTransaction.ts b/packages/tx/src/baseTransaction.ts index fa470039d0..e6a720c491 100644 --- a/packages/tx/src/baseTransaction.ts +++ b/packages/tx/src/baseTransaction.ts @@ -87,7 +87,7 @@ export abstract class BaseTransaction { * * @hidden */ - protected DEFAULT_HARDFORK: string | Hardfork = Hardfork.Merge + protected DEFAULT_HARDFORK: string | Hardfork = Hardfork.Paris constructor(txData: TxData | AccessListEIP2930TxData | FeeMarketEIP1559TxData, opts: TxOptions) { const { nonce, gasLimit, to, value, data, v, r, s, type } = txData diff --git a/packages/tx/test/eip3860.spec.ts b/packages/tx/test/eip3860.spec.ts index 42cd983e28..5b3fa411f3 100644 --- a/packages/tx/test/eip3860.spec.ts +++ b/packages/tx/test/eip3860.spec.ts @@ -6,7 +6,7 @@ import { TransactionFactory } from '../src' const common = new Common({ chain: Chain.Mainnet, - hardfork: Hardfork.Merge, + hardfork: Hardfork.Paris, eips: [3860, 4844, 4895], }) diff --git a/packages/vm/src/runTx.ts b/packages/vm/src/runTx.ts index ec5d15b6d2..a41f3a1e41 100644 --- a/packages/vm/src/runTx.ts +++ b/packages/vm/src/runTx.ts @@ -49,7 +49,7 @@ function execHardfork( hardfork: Hardfork | string, preMergeHf: Hardfork | string ): string | Hardfork { - return hardfork !== Hardfork.Merge ? hardfork : preMergeHf + return hardfork !== Hardfork.Paris ? hardfork : preMergeHf } /** diff --git a/packages/vm/src/types.ts b/packages/vm/src/types.ts index 4c949a3365..40469b4791 100644 --- a/packages/vm/src/types.ts +++ b/packages/vm/src/types.ts @@ -83,7 +83,7 @@ export interface VMOpts { * ### Possible Values * * - `chain`: all chains supported by `Common` or a custom chain - * - `hardfork`: `mainnet` hardforks up to the `Merge` hardfork + * - `hardfork`: `mainnet` hardforks up to the `Paris` hardfork * - `eips`: `2537` (usage e.g. `eips: [ 2537, ]`) * * Note: check the associated `@ethereumjs/evm` instance options @@ -94,7 +94,7 @@ export interface VMOpts { * Default setup if no `Common` instance is provided: * * - `chain`: `mainnet` - * - `hardfork`: `merge` + * - `hardfork`: `paris` * - `eips`: `[]` */ common?: Common @@ -136,13 +136,13 @@ export interface VMOpts { */ hardforkByBlockNumber?: boolean /** - * Select the HF by total difficulty (Merge HF) + * Select the HF by total difficulty (Paris Merge HF) * * This option is a superset of `hardforkByBlockNumber` (so only use one of both options) * and determines the HF by both the block number and the TD. * * Since the TD is only a threshold the block number will in doubt take precedence (imagine - * e.g. both Merge and Shanghai HF blocks set and the block number from the block provided + * e.g. both Paris (Merge) and Shanghai HF blocks set and the block number from the block provided * pointing to a Shanghai block: this will lead to set the HF as Shanghai and not the Merge). */ hardforkByTTD?: BigIntLike diff --git a/packages/vm/test/api/EIPs/eip-3670-eof-code-validation.spec.ts b/packages/vm/test/api/EIPs/eip-3670-eof-code-validation.spec.ts index 38a3f469d9..e35c7c5554 100644 --- a/packages/vm/test/api/EIPs/eip-3670-eof-code-validation.spec.ts +++ b/packages/vm/test/api/EIPs/eip-3670-eof-code-validation.spec.ts @@ -95,7 +95,7 @@ tape('EIP 3670 tests', (t) => { t.test('ensure invalid eof headers are rejected when calling', async (st) => { const common = new Common({ chain: Chain.Mainnet, - hardfork: Hardfork.Merge, + hardfork: Hardfork.Paris, eips: [3540, 3670], }) const vm = await VM.create({ common }) diff --git a/packages/vm/test/api/EIPs/eip-4399-supplant-difficulty-opcode-with-prevrando.spec.ts b/packages/vm/test/api/EIPs/eip-4399-supplant-difficulty-opcode-with-prevrando.spec.ts index 6e47a039b0..d8dce31a3f 100644 --- a/packages/vm/test/api/EIPs/eip-4399-supplant-difficulty-opcode-with-prevrando.spec.ts +++ b/packages/vm/test/api/EIPs/eip-4399-supplant-difficulty-opcode-with-prevrando.spec.ts @@ -40,7 +40,7 @@ tape('EIP-4399 -> 0x44 (DIFFICULTY) should return PREVRANDAO', (t) => { await vm.evm.runCode!({ ...runCodeArgs, block }) st.equal(stack[0], block.header.difficulty, '0x44 returns DIFFICULTY (London)') - common.setHardfork(Hardfork.Merge) + common.setHardfork(Hardfork.Paris) const prevRandao = bytesToBigInt(new Uint8Array(32).fill(1)) block = Block.fromBlockData( { diff --git a/packages/vm/test/api/EIPs/eip-4895-withdrawals.spec.ts b/packages/vm/test/api/EIPs/eip-4895-withdrawals.spec.ts index 71b59db0dc..d1009c6fe9 100644 --- a/packages/vm/test/api/EIPs/eip-4895-withdrawals.spec.ts +++ b/packages/vm/test/api/EIPs/eip-4895-withdrawals.spec.ts @@ -14,7 +14,7 @@ import type { WithdrawalBytes, WithdrawalData } from '@ethereumjs/util' const common = new Common({ chain: Chain.Mainnet, - hardfork: Hardfork.Merge, + hardfork: Hardfork.Paris, eips: [4895], }) diff --git a/packages/vm/test/api/index.spec.ts b/packages/vm/test/api/index.spec.ts index 61f7b7cb72..277eff82d5 100644 --- a/packages/vm/test/api/index.spec.ts +++ b/packages/vm/test/api/index.spec.ts @@ -42,7 +42,7 @@ tape('VM -> basic instantiation / boolean switches', (t) => { KECCAK256_RLP, 'it has default trie' ) - st.equal(vm._common.hardfork(), Hardfork.Merge, 'it has correct default HF') + st.equal(vm._common.hardfork(), Hardfork.Paris, 'it has correct default HF') st.end() }) @@ -77,7 +77,7 @@ tape('VM -> supportedHardforks', (t) => { Hardfork.ArrowGlacier, Hardfork.GrayGlacier, Hardfork.MergeForkIdTransition, - Hardfork.Merge, + Hardfork.Paris, ] try { await VM.create({ common }) diff --git a/packages/vm/test/api/runTx.spec.ts b/packages/vm/test/api/runTx.spec.ts index 7fa892e5fd..c67e256ffd 100644 --- a/packages/vm/test/api/runTx.spec.ts +++ b/packages/vm/test/api/runTx.spec.ts @@ -101,7 +101,7 @@ tape('runTx() -> successful API parameter usage', async (t) => { await vm.eei.putAccount(caller, acc) const block = Block.fromBlockData({}, { common: vm._common.copy() }) - block._common.setHardfork(Hardfork.Merge) + block._common.setHardfork(Hardfork.Paris) try { await vm.runTx({ tx, block }) st.fail('vm/block mismatched hardfork should have failed') @@ -115,7 +115,7 @@ tape('runTx() -> successful API parameter usage', async (t) => { } tx.common.setHardfork(Hardfork.London) - block._common.setHardfork(Hardfork.Merge) + block._common.setHardfork(Hardfork.Paris) try { await vm.runTx({ tx, block }) st.fail('vm/tx mismatched hardfork should have failed') @@ -135,7 +135,7 @@ tape('runTx() -> successful API parameter usage', async (t) => { }) t.test('should ignore merge in hardfork mismatch', async (st) => { - const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Merge }) + const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Paris }) const vm = await VM.create({ common, blockchain: await Blockchain.create({ validateConsensus: false, validateBlocks: false }), diff --git a/packages/vm/test/api/testdata/testnetMerge.json b/packages/vm/test/api/testdata/testnetMerge.json index c7ed5626a4..995d7b1d2a 100644 --- a/packages/vm/test/api/testdata/testnetMerge.json +++ b/packages/vm/test/api/testdata/testnetMerge.json @@ -53,7 +53,7 @@ "block": 14 }, { - "name": "merge", + "name": "paris", "block": null, "ttd": "5000" }, diff --git a/packages/vm/test/api/tester/tester.config.spec.ts b/packages/vm/test/api/tester/tester.config.spec.ts index b565996a36..53d21d6358 100644 --- a/packages/vm/test/api/tester/tester.config.spec.ts +++ b/packages/vm/test/api/tester/tester.config.spec.ts @@ -47,7 +47,7 @@ tape('bloom', (t: tape.Test) => { const str = testCase.hf + 'ToMergeAtDiff' + testCase.TTD.toString(16) const common = getCommon(str) st.ok(common.hardfork() === testCase.hf) - st.ok(common.hardforkTTD('merge') === BigInt(testCase.TTD)) + st.ok(common.hardforkTTD('paris') === BigInt(testCase.TTD)) }) st.end() }) diff --git a/packages/vm/test/retesteth/clients/ethereumjs/config b/packages/vm/test/retesteth/clients/ethereumjs/config index 13a737e171..cef98e640e 100644 --- a/packages/vm/test/retesteth/clients/ethereumjs/config +++ b/packages/vm/test/retesteth/clients/ethereumjs/config @@ -13,7 +13,7 @@ "Istanbul", "Berlin", "London", - "Merge", + "Paris", "Shanghai" ], "additionalForks":[ diff --git a/packages/vm/test/retesteth/clients/ethereumjs/genesis/correctMiningReward.json b/packages/vm/test/retesteth/clients/ethereumjs/genesis/correctMiningReward.json index be4bcc97a7..41617b5913 100644 --- a/packages/vm/test/retesteth/clients/ethereumjs/genesis/correctMiningReward.json +++ b/packages/vm/test/retesteth/clients/ethereumjs/genesis/correctMiningReward.json @@ -10,7 +10,7 @@ "Istanbul": "2000000000000000000", "Berlin": "2000000000000000000", "London": "2000000000000000000", - "Merge": "2000000000000000000", + "Paris": "2000000000000000000", "Merged": "2000000000000000000", "Shanghai": "2000000000000000000", diff --git a/packages/vm/test/tester/config.ts b/packages/vm/test/tester/config.ts index 89d98244fa..153913d563 100644 --- a/packages/vm/test/tester/config.ts +++ b/packages/vm/test/tester/config.ts @@ -9,7 +9,7 @@ export const DEFAULT_TESTS_PATH = path.resolve('../ethereum-tests') /** * Default hardfork rules to run tests against */ -export const DEFAULT_FORK_CONFIG = 'Merge' +export const DEFAULT_FORK_CONFIG = 'Paris' /** * Tests which should be fixed @@ -152,6 +152,10 @@ export function getRequiredForkConfigAlias(forkConfig: string) { if (String(forkConfig).match(/^petersburg$/i)) { return 'ConstantinopleFix' } + // Paris is named Merge + if (String(forkConfig).match(/^paris/i)) { + return 'Merge' + } return forkConfig } @@ -168,7 +172,7 @@ const normalHardforks = [ 'muirGlacier', 'berlin', 'london', - 'merge', + 'paris', 'shanghai', 'arrowGlacier', // This network has no tests, but need to add it due to common generation logic ] @@ -223,7 +227,7 @@ const retestethAlias = { EIP150: 'tangerineWhistle', EIP158: 'spuriousDragon', ConstantinopleFix: 'petersburg', - Merged: 'merge', + Merged: 'paris', } const testLegacy = { @@ -238,7 +242,7 @@ const testLegacy = { muirGlacier: false, berlin: false, london: false, - merge: false, + paris: false, ByzantiumToConstantinopleFixAt5: false, EIP158ToByzantiumAt5: false, FrontierToHomesteadAt5: false, @@ -308,7 +312,7 @@ function setupCommonWithNetworks(network: string, ttd?: number) { //forkHash: hf.forkHash, block: null, }) - } else if (hf.name === 'merge') { + } else if (hf.name === 'paris') { // merge will currently always be after a hardfork, so add it here testHardforks.push({ name: hf.name, @@ -429,7 +433,7 @@ const expectedTestsFull: { Berlin: 41365, London: 61197, ArrowGlacier: 0, - Merge: 60373, + Paris: 60373, Shanghai: 61563, ByzantiumToConstantinopleFixAt5: 3, EIP158ToByzantiumAt5: 3, @@ -451,7 +455,7 @@ const expectedTestsFull: { MuirGlacier: 12439, Berlin: 13214, London: 19449, - Merge: 19598, + Paris: 19598, Shanghai: 19564, ByzantiumToConstantinopleFixAt5: 0, EIP158ToByzantiumAt5: 0, diff --git a/packages/vm/test/util.ts b/packages/vm/test/util.ts index 426df08850..64bc2487f4 100644 --- a/packages/vm/test/util.ts +++ b/packages/vm/test/util.ts @@ -305,7 +305,7 @@ export function makeBlockHeader(data: any, opts?: BlockOptions) { headerData['baseFeePerGas'] = parentBlockHeader.calcNextBaseFee() } } - if (opts?.common && opts.common.gteHardfork('merge')) { + if (opts?.common && opts.common.gteHardfork('paris')) { headerData['mixHash'] = currentRandom headerData['difficulty'] = 0 } From 8f5cce2023623ba940b290d69b956c3601884c17 Mon Sep 17 00:00:00 2001 From: g11tech Date: Sat, 22 Apr 2023 02:07:13 +0530 Subject: [PATCH 18/53] common: Make Shanghai the default hardfork (#2655) * common: Make Shanghai the default hardfork * fx * fx spec * fixes * fix spec --- packages/client/test/sync/txpool.spec.ts | 18 +++++++++++------- packages/common/src/chains/goerli.json | 2 +- packages/common/src/chains/mainnet.json | 2 +- packages/common/src/chains/sepolia.json | 2 +- packages/common/src/common.ts | 2 +- packages/common/test/chains.spec.ts | 4 ++-- packages/tx/src/baseTransaction.ts | 2 +- packages/vm/test/api/EIPs/eip-3860.spec.ts | 22 ++++++++++++++-------- packages/vm/test/api/index.spec.ts | 2 +- 9 files changed, 33 insertions(+), 23 deletions(-) diff --git a/packages/client/test/sync/txpool.spec.ts b/packages/client/test/sync/txpool.spec.ts index f174186a6f..a3cc5dd907 100644 --- a/packages/client/test/sync/txpool.spec.ts +++ b/packages/client/test/sync/txpool.spec.ts @@ -478,15 +478,19 @@ tape('[TxPool]', async (t) => { }) t.test('announcedTxHashes() -> reject txs with too much data', async (t) => { - const txs = [] + const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Paris }) + const txs = [] txs.push( - FeeMarketEIP1559Transaction.fromTxData({ - maxFeePerGas: 1000000000, - maxPriorityFeePerGas: 1000000000, - nonce: 0, - data: '0x' + '00'.repeat(128 * 1024 + 1), - }).sign(A.privateKey) + FeeMarketEIP1559Transaction.fromTxData( + { + maxFeePerGas: 1000000000, + maxPriorityFeePerGas: 1000000000, + nonce: 0, + data: '0x' + '00'.repeat(128 * 1024 + 1), + }, + { common } + ).sign(A.privateKey) ) t.notOk( diff --git a/packages/common/src/chains/goerli.json b/packages/common/src/chains/goerli.json index 20650e4b76..691a346431 100644 --- a/packages/common/src/chains/goerli.json +++ b/packages/common/src/chains/goerli.json @@ -2,7 +2,7 @@ "name": "goerli", "chainId": 5, "networkId": 5, - "defaultHardfork": "paris", + "defaultHardfork": "shanghai", "consensus": { "type": "poa", "algorithm": "clique", diff --git a/packages/common/src/chains/mainnet.json b/packages/common/src/chains/mainnet.json index 813cb4cd57..9d97a71809 100644 --- a/packages/common/src/chains/mainnet.json +++ b/packages/common/src/chains/mainnet.json @@ -2,7 +2,7 @@ "name": "mainnet", "chainId": 1, "networkId": 1, - "defaultHardfork": "paris", + "defaultHardfork": "shanghai", "consensus": { "type": "pow", "algorithm": "ethash", diff --git a/packages/common/src/chains/sepolia.json b/packages/common/src/chains/sepolia.json index 8c1568ae1f..ffa7b59469 100644 --- a/packages/common/src/chains/sepolia.json +++ b/packages/common/src/chains/sepolia.json @@ -2,7 +2,7 @@ "name": "sepolia", "chainId": 11155111, "networkId": 11155111, - "defaultHardfork": "paris", + "defaultHardfork": "shanghai", "consensus": { "type": "pow", "algorithm": "ethash", diff --git a/packages/common/src/common.ts b/packages/common/src/common.ts index b781073c8e..aa977ba2da 100644 --- a/packages/common/src/common.ts +++ b/packages/common/src/common.ts @@ -235,7 +235,7 @@ export class Common extends EventEmitter { super() this._customChains = opts.customChains ?? [] this._chainParams = this.setChain(opts.chain) - this.DEFAULT_HARDFORK = this._chainParams.defaultHardfork ?? Hardfork.Paris + this.DEFAULT_HARDFORK = this._chainParams.defaultHardfork ?? Hardfork.Shanghai // Assign hardfork changes in the sequence of the applied hardforks this.HARDFORK_CHANGES = this.hardforks().map((hf) => [ hf.name as HardforkSpecKeys, diff --git a/packages/common/test/chains.spec.ts b/packages/common/test/chains.spec.ts index 9518d58f39..f967ae33b2 100644 --- a/packages/common/test/chains.spec.ts +++ b/packages/common/test/chains.spec.ts @@ -8,7 +8,7 @@ tape('[Common/Chains]: Initialization / Chain params', function (t: tape.Test) { st.equal(c.chainName(), 'mainnet', 'should initialize with chain name') st.equal(c.chainId(), BigInt(1), 'should return correct chain Id') st.equal(c.networkId(), BigInt(1), 'should return correct network Id') - st.equal(c.hardfork(), Hardfork.Paris, 'should set hardfork to current default hardfork') + st.equal(c.hardfork(), Hardfork.Shanghai, 'should set hardfork to current default hardfork') st.equal( c.hardfork(), c.DEFAULT_HARDFORK, @@ -26,7 +26,7 @@ tape('[Common/Chains]: Initialization / Chain params', function (t: tape.Test) { st.equal(c.chainName(), 'mainnet', 'should initialize with chain name') st.equal(c.chainId(), BigInt(1), 'should return correct chain Id') st.equal(c.networkId(), BigInt(1), 'should return correct network Id') - st.equal(c.hardfork(), Hardfork.Paris, 'should set hardfork to current default hardfork') + st.equal(c.hardfork(), Hardfork.Shanghai, 'should set hardfork to current default hardfork') st.equal( c.hardfork(), c.DEFAULT_HARDFORK, diff --git a/packages/tx/src/baseTransaction.ts b/packages/tx/src/baseTransaction.ts index e6a720c491..d0e58ac591 100644 --- a/packages/tx/src/baseTransaction.ts +++ b/packages/tx/src/baseTransaction.ts @@ -87,7 +87,7 @@ export abstract class BaseTransaction { * * @hidden */ - protected DEFAULT_HARDFORK: string | Hardfork = Hardfork.Paris + protected DEFAULT_HARDFORK: string | Hardfork = Hardfork.Shanghai constructor(txData: TxData | AccessListEIP2930TxData | FeeMarketEIP1559TxData, opts: TxOptions) { const { nonce, gasLimit, to, value, data, v, r, s, type } = txData diff --git a/packages/vm/test/api/EIPs/eip-3860.spec.ts b/packages/vm/test/api/EIPs/eip-3860.spec.ts index 6231a56a63..cf3a0d8008 100644 --- a/packages/vm/test/api/EIPs/eip-3860.spec.ts +++ b/packages/vm/test/api/EIPs/eip-3860.spec.ts @@ -25,14 +25,20 @@ tape('EIP 3860 tests', (t) => { await vm.stateManager.putAccount(sender, account!) const bytes = new Uint8Array(1000000).fill(0x60) - const tx = FeeMarketEIP1559Transaction.fromTxData({ - data: - '0x7F6000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060005260206000F3' + - bytesToHex(bytes), - gasLimit: 100000000000, - maxFeePerGas: 7, - nonce: 0, - }).sign(pkey) + // We create a tx with a common which has eip not yet activated else tx creation will + // throw error + const txCommon = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.London }) + const tx = FeeMarketEIP1559Transaction.fromTxData( + { + data: + '0x7F6000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060005260206000F3' + + bytesToHex(bytes), + gasLimit: 100000000000, + maxFeePerGas: 7, + nonce: 0, + }, + { common: txCommon } + ).sign(pkey) const result = await vm.runTx({ tx }) st.ok( (result.execResult.exceptionError?.error as string) === 'initcode exceeds max initcode size', diff --git a/packages/vm/test/api/index.spec.ts b/packages/vm/test/api/index.spec.ts index 277eff82d5..fa2459c0be 100644 --- a/packages/vm/test/api/index.spec.ts +++ b/packages/vm/test/api/index.spec.ts @@ -42,7 +42,7 @@ tape('VM -> basic instantiation / boolean switches', (t) => { KECCAK256_RLP, 'it has default trie' ) - st.equal(vm._common.hardfork(), Hardfork.Paris, 'it has correct default HF') + st.equal(vm._common.hardfork(), Hardfork.Shanghai, 'it has correct default HF') st.end() }) From c2ae0287c823d18ff17bd5a959b7d63ed665c619 Mon Sep 17 00:00:00 2001 From: Holger Drewes Date: Fri, 21 Apr 2023 23:45:13 +0200 Subject: [PATCH 19/53] Statemanager: Fix Cache Commit Bug (#2653) * StateManager: fix account cache commit bug, add test case * StateManager: fix storage cache commit bug, add test case * StateManager: fix account cache commit, added note on storage cach e commit * StateManager: fix storage part of cache commit bug --------- Co-authored-by: acolytec3 <17355484+acolytec3@users.noreply.github.com> --- packages/statemanager/src/cache/account.ts | 8 ++++---- packages/statemanager/src/cache/storage.ts | 8 ++++---- .../statemanager/test/cache/account.spec.ts | 18 +++++++++++++++--- .../statemanager/test/cache/storage.spec.ts | 14 ++++++++++++++ .../test/ethersStateManager.spec.ts | 2 +- 5 files changed, 38 insertions(+), 12 deletions(-) diff --git a/packages/statemanager/src/cache/account.ts b/packages/statemanager/src/cache/account.ts index f2dbb036e0..f41c2da85a 100644 --- a/packages/statemanager/src/cache/account.ts +++ b/packages/statemanager/src/cache/account.ts @@ -208,10 +208,10 @@ export class AccountCache extends Cache { const it = diffMap.begin() while (!it.equals(diffMap.end())) { const addressHex = it.pointer[0] - const element = it.pointer[1] - const oldElem = this._diffCache[this._checkpoints].getElementByKey(addressHex) - if (oldElem === undefined) { - this._diffCache[this._checkpoints].setElement(addressHex, element) + const itOld = this._diffCache[this._checkpoints].find(addressHex) + if (itOld.equals(this._diffCache[this._checkpoints].end())) { + const elem = it.pointer[1] + this._diffCache[this._checkpoints].setElement(addressHex, elem) } it.next() } diff --git a/packages/statemanager/src/cache/storage.ts b/packages/statemanager/src/cache/storage.ts index 602bda650a..57fc603385 100644 --- a/packages/statemanager/src/cache/storage.ts +++ b/packages/statemanager/src/cache/storage.ts @@ -302,10 +302,10 @@ export class StorageCache extends Cache { while (!itHigherHeightStorageDiff.equals(higherHeightStorageDiff.end())) { const keyHex = itHigherHeightStorageDiff.pointer[0] - const value = itHigherHeightStorageDiff.pointer[1] - const lowerHeightDiffStorage = lowerHeightStorageDiff.getElementByKey(keyHex) - if (lowerHeightDiffStorage === undefined) { - lowerHeightStorageDiff.setElement(keyHex, value) + const lowerHeightIt = lowerHeightStorageDiff.find(keyHex) + if (lowerHeightIt.equals(lowerHeightStorageDiff.end())) { + const elem = itHigherHeightStorageDiff.pointer[1] + lowerHeightStorageDiff.setElement(keyHex, elem) } itHigherHeightStorageDiff.next() } diff --git a/packages/statemanager/test/cache/account.spec.ts b/packages/statemanager/test/cache/account.spec.ts index 3d44d93b38..cbd71e1f03 100644 --- a/packages/statemanager/test/cache/account.spec.ts +++ b/packages/statemanager/test/cache/account.spec.ts @@ -1,11 +1,9 @@ -import { Address, equalsBytes, hexStringToBytes } from '@ethereumjs/util' +import { Account, Address, equalsBytes, hexStringToBytes } from '@ethereumjs/util' import * as tape from 'tape' import { AccountCache, CacheType } from '../../src/cache' import { createAccount } from '../util' -import type { Account } from '@ethereumjs/util' - tape('Account Cache: initialization', (t) => { for (const type of [CacheType.LRU, CacheType.ORDERED_MAP]) { t.test('should initialize', async (st) => { @@ -84,6 +82,20 @@ tape('Account Cache: checkpointing', (t) => { st.end() }) + t.test('should use outer revert', async (st) => { + const cache = new AccountCache({ size: 100, type: CacheType.LRU }) + + const account1 = new Account(undefined, 1n) + cache.checkpoint() + cache.put(addr, account1) + cache.checkpoint() + cache.put(addr, account1) + cache.commit() + cache.revert() + const accCmp = cache.get(addr) + st.ok(accCmp === undefined) + }) + t.test('cache clearing', async (st) => { const cache = new AccountCache({ size: 100, type: CacheType.LRU }) cache.put(addr, acc) diff --git a/packages/statemanager/test/cache/storage.spec.ts b/packages/statemanager/test/cache/storage.spec.ts index 82836e6d4c..9e34d50d5e 100644 --- a/packages/statemanager/test/cache/storage.spec.ts +++ b/packages/statemanager/test/cache/storage.spec.ts @@ -80,6 +80,20 @@ tape('Storage Cache: checkpointing', (t) => { st.end() }) + t.test('should use outer revert', async (st) => { + const cache = new StorageCache({ size: 100, type }) + + cache.checkpoint() + cache.put(addr, key, value) + cache.checkpoint() + cache.put(addr, key, value) + cache.commit() + cache.revert() + + const elem = cache.get(addr, key) + st.ok(elem === undefined) + }) + t.test('should revert to unknown if nonexistent in cache before', async (st) => { const cache = new StorageCache({ size: 100, type }) diff --git a/packages/statemanager/test/ethersStateManager.spec.ts b/packages/statemanager/test/ethersStateManager.spec.ts index 4ce94c59a1..fbbe541878 100644 --- a/packages/statemanager/test/ethersStateManager.spec.ts +++ b/packages/statemanager/test/ethersStateManager.spec.ts @@ -182,7 +182,7 @@ tape('runTx custom transaction test', async (t) => { // The `MockProvider` is not able to load JSON files dynamically in browser so skipped in browser tests t.end() } else { - const common = new Common({ chain: Chain.Mainnet }) + const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.London }) const provider = process.env.PROVIDER !== undefined ? new StaticJsonRpcProvider(process.env.PROVIDER, 1) From 850d47c23e5cdb05663865f9f9bd76b2f6d2f5c6 Mon Sep 17 00:00:00 2001 From: g11tech Date: Sun, 23 Apr 2023 23:35:51 +0530 Subject: [PATCH 20/53] common: Fix the block's fromValuesArray common refernces (#2657) --- packages/block/src/block.ts | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/packages/block/src/block.ts b/packages/block/src/block.ts index c9dac4bea6..ee1cf6f093 100644 --- a/packages/block/src/block.ts +++ b/packages/block/src/block.ts @@ -152,9 +152,14 @@ export class Block { if (values.length > 4) { throw new Error('invalid block. More values than expected were received') } + + // First try to load header so that we can use its common (in case of hardforkByBlockNumber being activated) + // to correctly make checks on the hardforks + const [headerData, txsData, uhsData, withdrawalBytes] = values + const header = BlockHeader.fromValuesArray(headerData, opts) + if ( - opts?.common !== undefined && - opts?.common?.isActivatedEIP(4895) && + header._common.isActivatedEIP(4895) && (values[3] === undefined || !Array.isArray(values[3])) ) { throw new Error( @@ -162,10 +167,6 @@ export class Block { ) } - const [headerData, txsData, uhsData, withdrawalBytes] = values - - const header = BlockHeader.fromValuesArray(headerData, opts) - // parse transactions const transactions = [] for (const txData of txsData ?? []) { From e39505eabaf4c0262276e966b58a80baa6785eea Mon Sep 17 00:00:00 2001 From: g11tech Date: Sun, 23 Apr 2023 23:55:24 +0530 Subject: [PATCH 21/53] common: Rename shardingForkTime to cancunTime (#2658) --- packages/block/test/testdata/4844-hardfork.json | 2 +- packages/client/devnets/4844-interop/config/genesis.json | 2 +- packages/client/devnets/4844-interop/lighthouse/genesis.json | 2 +- packages/client/devnets/4844-interop/lighthouse/setup.sh | 2 +- packages/client/devnets/4844-interop/prysm/genesisGEN.json | 2 +- packages/client/devnets/4844-interop/prysm/prysm.json | 2 +- packages/client/test/sim/configs/sharding.json | 2 +- packages/client/test/testdata/geth-genesis/eip4844.json | 2 +- packages/common/src/utils.ts | 2 +- packages/common/test/timestamp.spec.ts | 4 ++-- 10 files changed, 11 insertions(+), 11 deletions(-) diff --git a/packages/block/test/testdata/4844-hardfork.json b/packages/block/test/testdata/4844-hardfork.json index ac09973c93..9ee53c6112 100644 --- a/packages/block/test/testdata/4844-hardfork.json +++ b/packages/block/test/testdata/4844-hardfork.json @@ -14,7 +14,7 @@ "berlinBlock": 0, "londonBlock": 0, "shanghaiTime": 0, - "shardingForkTime": 0, + "cancunTime": 0, "clique": { "period": 5, "epoch": 30000 diff --git a/packages/client/devnets/4844-interop/config/genesis.json b/packages/client/devnets/4844-interop/config/genesis.json index 3ca03b5dc3..34d5bb2c0d 100644 --- a/packages/client/devnets/4844-interop/config/genesis.json +++ b/packages/client/devnets/4844-interop/config/genesis.json @@ -20,7 +20,7 @@ "arrowGlacierBlock": 0, "grayGlacierBlock": 0, "shanghaiTime": 1673487257, - "shardingForkTime": 1673487293, + "cancunTime": 1673487293, "ethash": { }, "terminalTotalDifficulty": 50 diff --git a/packages/client/devnets/4844-interop/lighthouse/genesis.json b/packages/client/devnets/4844-interop/lighthouse/genesis.json index 09e4474226..431d8389cf 100755 --- a/packages/client/devnets/4844-interop/lighthouse/genesis.json +++ b/packages/client/devnets/4844-interop/lighthouse/genesis.json @@ -13,7 +13,7 @@ "londonBlock": 0, "mergeNetsplitBlock": 0, "shanghaiTime": 1674244123, - "shardingForkTime": 1674244219, + "cancunTime": 1674244219, "terminalTotalDifficulty": 80 }, "alloc": { diff --git a/packages/client/devnets/4844-interop/lighthouse/setup.sh b/packages/client/devnets/4844-interop/lighthouse/setup.sh index 28f6ecae84..52f13f3b4d 100755 --- a/packages/client/devnets/4844-interop/lighthouse/setup.sh +++ b/packages/client/devnets/4844-interop/lighthouse/setup.sh @@ -56,5 +56,5 @@ CAPELLA_TIME=$((GENESIS_TIME + (CAPELLA_FORK_EPOCH * 32 * SECONDS_PER_SLOT))) EIP4844_TIME=$((GENESIS_TIME + (EIP4844_FORK_EPOCH * 32 * SECONDS_PER_SLOT))) sed -i 's/"shanghaiTime".*$/"shanghaiTime": '"$CAPELLA_TIME"',/g' $DATADIR/genesis.json -sed -i 's/"shardingForkTime".*$/"shardingForkTime": '"$EIP4844_TIME"',/g' $DATADIR/genesis.json +sed -i 's/"cancunTime".*$/"cancunTime": '"$EIP4844_TIME"',/g' $DATADIR/genesis.json cp $DATADIR/genesis.json $TESTNET_DIR/genesis.json \ No newline at end of file diff --git a/packages/client/devnets/4844-interop/prysm/genesisGEN.json b/packages/client/devnets/4844-interop/prysm/genesisGEN.json index 7f37c9d2a4..88473fd6bc 100644 --- a/packages/client/devnets/4844-interop/prysm/genesisGEN.json +++ b/packages/client/devnets/4844-interop/prysm/genesisGEN.json @@ -20,7 +20,7 @@ "arrowGlacierBlock": 0, "grayGlacierBlock": 0, "shanghaiTime": 1674239093, - "shardingForkTime": 1674239129, + "cancunTime": 1674239129, "ethash": {}, "terminalTotalDifficulty": 50 }, diff --git a/packages/client/devnets/4844-interop/prysm/prysm.json b/packages/client/devnets/4844-interop/prysm/prysm.json index 0ab088c496..32d0fd8e8a 100644 --- a/packages/client/devnets/4844-interop/prysm/prysm.json +++ b/packages/client/devnets/4844-interop/prysm/prysm.json @@ -20,7 +20,7 @@ "arrowGlacierBlock": 0, "grayGlacierBlock": 0, "shanghaiTime": XXX, - "shardingForkTime": YYY, + "cancunTime": YYY, "ethash": { }, "terminalTotalDifficulty": 50 diff --git a/packages/client/test/sim/configs/sharding.json b/packages/client/test/sim/configs/sharding.json index f33450003a..4287403d32 100644 --- a/packages/client/test/sim/configs/sharding.json +++ b/packages/client/test/sim/configs/sharding.json @@ -15,7 +15,7 @@ "berlinBlock": 0, "londonBlock": 0, "shanghaiTime": 0, - "shardingForkTime": 0, + "cancunTime": 0, "clique": { "period": 5, "epoch": 30000 diff --git a/packages/client/test/testdata/geth-genesis/eip4844.json b/packages/client/test/testdata/geth-genesis/eip4844.json index eb687dc9b0..cd5726b939 100644 --- a/packages/client/test/testdata/geth-genesis/eip4844.json +++ b/packages/client/test/testdata/geth-genesis/eip4844.json @@ -13,7 +13,7 @@ "berlinBlock": 0, "londonBlock": 0, "shanghaiTime": 0, - "shardingForkTime": 0, + "cancunTime": 0, "clique": { "blockperiodseconds": 5, "epochlength": 30000 diff --git a/packages/common/src/utils.ts b/packages/common/src/utils.ts index de41bf2e37..bb0617e766 100644 --- a/packages/common/src/utils.ts +++ b/packages/common/src/utils.ts @@ -123,7 +123,7 @@ function parseGethParams(json: any, mergeForkIdPostMerge: boolean = true) { [Hardfork.London]: { name: 'londonBlock' }, [Hardfork.MergeForkIdTransition]: { name: 'mergeForkBlock', postMerge: mergeForkIdPostMerge }, [Hardfork.Shanghai]: { name: 'shanghaiTime', postMerge: true, isTimestamp: true }, - [Hardfork.ShardingForkDev]: { name: 'shardingForkTime', postMerge: true, isTimestamp: true }, + [Hardfork.ShardingForkDev]: { name: 'cancunTime', postMerge: true, isTimestamp: true }, } // forkMapRev is the map from config field name to Hardfork diff --git a/packages/common/test/timestamp.spec.ts b/packages/common/test/timestamp.spec.ts index 18ccb9a03d..a0d0fca88e 100644 --- a/packages/common/test/timestamp.spec.ts +++ b/packages/common/test/timestamp.spec.ts @@ -30,7 +30,7 @@ tape('[Common]: Timestamp Hardfork logic', function (t: tape.Test) { t.test('schedule sharding on shanghai-time', function (st: tape.Test) { const config = Object.assign({}, timestampJson.config, { - shardingForkTime: timestampJson.config.shanghaiTime, + cancunTime: timestampJson.config.shanghaiTime, }) const modifiedJson = Object.assign({}, timestampJson, { config }) const c = Common.fromGethGenesis(modifiedJson, { @@ -52,7 +52,7 @@ tape('[Common]: Timestamp Hardfork logic', function (t: tape.Test) { t.test('schedule sharding post shanghai-time', function (st: tape.Test) { const config = Object.assign({}, timestampJson.config, { - shardingForkTime: timestampJson.config.shanghaiTime + 1000, + cancunTime: timestampJson.config.shanghaiTime + 1000, }) const modifiedJson = Object.assign({}, timestampJson, { config }) const c = Common.fromGethGenesis(modifiedJson, { From 7a8af7ee1761568a98e9485047a45fa2d49102dd Mon Sep 17 00:00:00 2001 From: g11tech Date: Mon, 24 Apr 2023 13:36:33 +0530 Subject: [PATCH 22/53] common: Rename shardingForkDev hf to Cancun (#2659) * common: Rename shardingForkDev hf to Cancun * add cancun entries to chain configs * spec fixes * reset min hf * lint --- packages/block/test/eip4844block.spec.ts | 2 +- packages/client/devnets/4844-interop/tools/txGenerator.ts | 2 +- packages/client/lib/rpc/modules/engine.ts | 4 +--- packages/client/test/miner/pendingBlock.spec.ts | 2 +- .../test/rpc/engine/getPayloadBodiesByHashV1.spec.ts | 4 ++-- .../test/rpc/engine/getPayloadBodiesByRangeV1.spec.ts | 4 ++-- packages/client/test/rpc/engine/getPayloadV3.spec.ts | 6 +++--- packages/client/test/rpc/eth/getTransactionReceipt.spec.ts | 4 ++-- packages/client/test/rpc/eth/sendRawTransaction.spec.ts | 4 ++-- packages/common/docs/enums/Hardfork.md | 6 +++--- packages/common/src/chains/goerli.json | 5 +++++ packages/common/src/chains/mainnet.json | 5 +++++ packages/common/src/chains/sepolia.json | 5 +++++ packages/common/src/enums.ts | 2 +- packages/common/src/hardforks/cancun.json | 7 +++++++ packages/common/src/hardforks/index.ts | 2 +- packages/common/src/hardforks/sharding.json | 7 ------- packages/common/src/utils.ts | 2 +- packages/evm/src/evm.ts | 2 +- packages/evm/test/precompiles/14-pointevaluation.spec.ts | 2 +- packages/evm/test/runCall.spec.ts | 2 +- packages/tx/test/eip4844.spec.ts | 2 +- packages/vm/test/api/runTx.spec.ts | 4 ++-- 23 files changed, 49 insertions(+), 36 deletions(-) create mode 100644 packages/common/src/hardforks/cancun.json delete mode 100644 packages/common/src/hardforks/sharding.json diff --git a/packages/block/test/eip4844block.spec.ts b/packages/block/test/eip4844block.spec.ts index 9813e03254..adb8367f8c 100644 --- a/packages/block/test/eip4844block.spec.ts +++ b/packages/block/test/eip4844block.spec.ts @@ -21,7 +21,7 @@ if (isBrowser() === false) initKZG(kzg, __dirname + '/../../client/lib/trustedSe const gethGenesis = require('./testdata/4844-hardfork.json') const common = Common.fromGethGenesis(gethGenesis, { chain: 'customChain', - hardfork: Hardfork.ShardingForkDev, + hardfork: Hardfork.Cancun, }) tape('EIP4844 header tests', function (t) { diff --git a/packages/client/devnets/4844-interop/tools/txGenerator.ts b/packages/client/devnets/4844-interop/tools/txGenerator.ts index 53bd429a0c..0e32ff562b 100644 --- a/packages/client/devnets/4844-interop/tools/txGenerator.ts +++ b/packages/client/devnets/4844-interop/tools/txGenerator.ts @@ -26,7 +26,7 @@ initKZG(kzg, __dirname + '/../../../lib/trustedSetups/devnet4.txt') const sender = Address.fromPrivateKey(pkey) const common = Common.fromGethGenesis(genesisJson, { chain: genesisJson.ChainName ?? 'devnet', - hardfork: Hardfork.ShardingForkDev, + hardfork: Hardfork.Cancun, }) async function getNonce(client: Client, account: string) { const nonce = await client.request('eth_getTransactionCount', [account, 'latest'], 2.0) diff --git a/packages/client/lib/rpc/modules/engine.ts b/packages/client/lib/rpc/modules/engine.ts index 8972ea1278..cf99a7b667 100644 --- a/packages/client/lib/rpc/modules/engine.ts +++ b/packages/client/lib/rpc/modules/engine.ts @@ -682,9 +682,7 @@ export class Engine { params: [ExecutionPayloadV3 | ExecutionPayloadV2 | ExecutionPayloadV1] ): Promise { const shanghaiTimestamp = this.chain.config.chainCommon.hardforkTimestamp(Hardfork.Shanghai) - const eip4844Timestamp = this.chain.config.chainCommon.hardforkTimestamp( - Hardfork.ShardingForkDev - ) + const eip4844Timestamp = this.chain.config.chainCommon.hardforkTimestamp(Hardfork.Cancun) if (shanghaiTimestamp === null || parseInt(params[0].timestamp) < shanghaiTimestamp) { if ('withdrawals' in params[0]) { throw { diff --git a/packages/client/test/miner/pendingBlock.spec.ts b/packages/client/test/miner/pendingBlock.spec.ts index ae25ba3bcf..c92acd185d 100644 --- a/packages/client/test/miner/pendingBlock.spec.ts +++ b/packages/client/test/miner/pendingBlock.spec.ts @@ -272,7 +272,7 @@ tape('[PendingBlock]', async (t) => { const gethGenesis = require('../../../block/test/testdata/4844-hardfork.json') const common = Common.fromGethGenesis(gethGenesis, { chain: 'customChain', - hardfork: Hardfork.ShardingForkDev, + hardfork: Hardfork.Cancun, }) const { txPool } = setup() const blobs = getBlobs('hello world') diff --git a/packages/client/test/rpc/engine/getPayloadBodiesByHashV1.spec.ts b/packages/client/test/rpc/engine/getPayloadBodiesByHashV1.spec.ts index a268128599..9362cb56bb 100644 --- a/packages/client/test/rpc/engine/getPayloadBodiesByHashV1.spec.ts +++ b/packages/client/test/rpc/engine/getPayloadBodiesByHashV1.spec.ts @@ -44,9 +44,9 @@ tape(`${method}: call with valid parameters`, async (t) => { } const { chain, service, server, common } = await setupChain(genesisJSON, 'post-merge', { engine: true, - hardfork: Hardfork.ShardingForkDev, + hardfork: Hardfork.Cancun, }) - common.setHardfork(Hardfork.ShardingForkDev) + common.setHardfork(Hardfork.Cancun) const pkey = hexStringToBytes('9c9996335451aab4fc4eac58e31a8c300e095cdbcee532d53d09280e83360355') const address = Address.fromPrivateKey(pkey) await service.execution.vm.stateManager.putAccount(address, new Account()) diff --git a/packages/client/test/rpc/engine/getPayloadBodiesByRangeV1.spec.ts b/packages/client/test/rpc/engine/getPayloadBodiesByRangeV1.spec.ts index 650e43bde8..8821cfabf8 100644 --- a/packages/client/test/rpc/engine/getPayloadBodiesByRangeV1.spec.ts +++ b/packages/client/test/rpc/engine/getPayloadBodiesByRangeV1.spec.ts @@ -47,9 +47,9 @@ tape(`${method}: call with valid parameters`, async (t) => { } const { chain, service, server, common } = await setupChain(genesisJSON, 'post-merge', { engine: true, - hardfork: Hardfork.ShardingForkDev, + hardfork: Hardfork.Cancun, }) - common.setHardfork(Hardfork.ShardingForkDev) + common.setHardfork(Hardfork.Cancun) const pkey = hexStringToBytes('9c9996335451aab4fc4eac58e31a8c300e095cdbcee532d53d09280e83360355') const address = Address.fromPrivateKey(pkey) await service.execution.vm.stateManager.putAccount(address, new Account()) diff --git a/packages/client/test/rpc/engine/getPayloadV3.spec.ts b/packages/client/test/rpc/engine/getPayloadV3.spec.ts index 0555b7b4e3..21ac158808 100644 --- a/packages/client/test/rpc/engine/getPayloadV3.spec.ts +++ b/packages/client/test/rpc/engine/getPayloadV3.spec.ts @@ -68,9 +68,9 @@ tape(`${method}: call with known payload`, async (t) => { } const { service, server, common } = await setupChain(genesisJSON, 'post-merge', { engine: true, - hardfork: Hardfork.ShardingForkDev, + hardfork: Hardfork.Cancun, }) - common.setHardfork(Hardfork.ShardingForkDev) + common.setHardfork(Hardfork.Cancun) const pkey = hexStringToBytes('9c9996335451aab4fc4eac58e31a8c300e095cdbcee532d53d09280e83360355') const address = Address.fromPrivateKey(pkey) await service.execution.vm.stateManager.putAccount(address, new Account()) @@ -105,7 +105,7 @@ tape(`${method}: call with known payload`, async (t) => { { common } ).sign(pkey) - ;(service.txPool as any).vm._common.setHardfork(Hardfork.ShardingForkDev) + ;(service.txPool as any).vm._common.setHardfork(Hardfork.Cancun) await service.txPool.add(tx, true) req = params('engine_getPayloadV3', [payloadId]) expectRes = (res: any) => { diff --git a/packages/client/test/rpc/eth/getTransactionReceipt.spec.ts b/packages/client/test/rpc/eth/getTransactionReceipt.spec.ts index f7c2a097af..cc6a0ecdc5 100644 --- a/packages/client/test/rpc/eth/getTransactionReceipt.spec.ts +++ b/packages/client/test/rpc/eth/getTransactionReceipt.spec.ts @@ -101,10 +101,10 @@ tape(`${method}: get dataGasUsed/dataGasPrice in blob tx receipt`, async (t) => const gethGenesis = require('../../../../block/test/testdata/4844-hardfork.json') const common = Common.fromGethGenesis(gethGenesis, { chain: 'customChain', - hardfork: Hardfork.ShardingForkDev, + hardfork: Hardfork.Cancun, }) const { chain, execution, server } = await setupChain(gethGenesis, 'customChain') - common.setHardfork(Hardfork.ShardingForkDev) + common.setHardfork(Hardfork.Cancun) const blobs = getBlobs('hello world') const commitments = blobsToCommitments(blobs) diff --git a/packages/client/test/rpc/eth/sendRawTransaction.spec.ts b/packages/client/test/rpc/eth/sendRawTransaction.spec.ts index c6b7863dd3..11a70976bb 100644 --- a/packages/client/test/rpc/eth/sendRawTransaction.spec.ts +++ b/packages/client/test/rpc/eth/sendRawTransaction.spec.ts @@ -227,9 +227,9 @@ tape('blob EIP 4844 transaction', async (t) => { const gethGenesis = require('../../../../block/test/testdata/4844-hardfork.json') const common = Common.fromGethGenesis(gethGenesis, { chain: 'customChain', - hardfork: Hardfork.ShardingForkDev, + hardfork: Hardfork.Cancun, }) - common.setHardfork(Hardfork.ShardingForkDev) + common.setHardfork(Hardfork.Cancun) const { server, client } = baseSetup({ commonChain: common, includeVM: true, diff --git a/packages/common/docs/enums/Hardfork.md b/packages/common/docs/enums/Hardfork.md index d204c7c369..143608ef66 100644 --- a/packages/common/docs/enums/Hardfork.md +++ b/packages/common/docs/enums/Hardfork.md @@ -21,7 +21,7 @@ - [MuirGlacier](Hardfork.md#muirglacier) - [Petersburg](Hardfork.md#petersburg) - [Shanghai](Hardfork.md#shanghai) -- [ShardingForkDev](Hardfork.md#shardingforkdev) +- [Cancun](Hardfork.md#Cancun) - [SpuriousDragon](Hardfork.md#spuriousdragon) - [TangerineWhistle](Hardfork.md#tangerinewhistle) @@ -177,9 +177,9 @@ ___ ___ -### ShardingForkDev +### Cancun -• **ShardingForkDev** = ``"shardingFork"`` +• **Cancun** = ``"cancun"`` #### Defined in diff --git a/packages/common/src/chains/goerli.json b/packages/common/src/chains/goerli.json index 691a346431..7d1016fe88 100644 --- a/packages/common/src/chains/goerli.json +++ b/packages/common/src/chains/goerli.json @@ -88,6 +88,11 @@ "block": null, "timestamp": "1678832736", "forkHash": "0xf9843abf" + }, + { + "name": "cancun", + "block": null, + "forkHash": null } ], "bootstrapNodes": [ diff --git a/packages/common/src/chains/mainnet.json b/packages/common/src/chains/mainnet.json index 9d97a71809..c930717030 100644 --- a/packages/common/src/chains/mainnet.json +++ b/packages/common/src/chains/mainnet.json @@ -104,6 +104,11 @@ "block": null, "timestamp": "1681338455", "forkHash": "0xdce96c2d" + }, + { + "name": "cancun", + "block": null, + "forkHash": null } ], "bootstrapNodes": [ diff --git a/packages/common/src/chains/sepolia.json b/packages/common/src/chains/sepolia.json index ffa7b59469..7bb93238f8 100644 --- a/packages/common/src/chains/sepolia.json +++ b/packages/common/src/chains/sepolia.json @@ -90,6 +90,11 @@ "block": null, "timestamp": "1677557088", "forkHash": "0xf7f9bc08" + }, + { + "name": "cancun", + "block": null, + "forkHash": null } ], "bootstrapNodes": [ diff --git a/packages/common/src/enums.ts b/packages/common/src/enums.ts index cc1897679b..feca2961c8 100644 --- a/packages/common/src/enums.ts +++ b/packages/common/src/enums.ts @@ -24,7 +24,7 @@ export enum Hardfork { MergeForkIdTransition = 'mergeForkIdTransition', Paris = 'paris', Shanghai = 'shanghai', - ShardingForkDev = 'shardingFork', + Cancun = 'cancun', } export enum ConsensusType { diff --git a/packages/common/src/hardforks/cancun.json b/packages/common/src/hardforks/cancun.json new file mode 100644 index 0000000000..8842abfde3 --- /dev/null +++ b/packages/common/src/hardforks/cancun.json @@ -0,0 +1,7 @@ +{ + "name": "cancun", + "comment": "Next feature hardfork after the shanghai having proto-danksharding EIP 4844 blobs (still WIP hence not for production use)", + "url": "https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/cancun.md", + "status": "Experimental", + "eips": [4844] +} diff --git a/packages/common/src/hardforks/index.ts b/packages/common/src/hardforks/index.ts index 36e1fcb90d..b276b607e8 100644 --- a/packages/common/src/hardforks/index.ts +++ b/packages/common/src/hardforks/index.ts @@ -16,5 +16,5 @@ export const hardforks = { grayGlacier: require('./grayGlacier.json'), mergeForkIdTransition: require('./mergeForkIdTransition.json'), paris: require('./paris.json'), - shardingFork: require('./sharding.json'), + cancun: require('./cancun.json'), } diff --git a/packages/common/src/hardforks/sharding.json b/packages/common/src/hardforks/sharding.json deleted file mode 100644 index 0b0eb0afb5..0000000000 --- a/packages/common/src/hardforks/sharding.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name": "shardingFork", - "comment": "Internal hardfork to test proto-danksharding (do not use in production)", - "url": "https://eips.ethereum.org/EIPS/eip-4844", - "status": "Experimental", - "eips": [4844] -} diff --git a/packages/common/src/utils.ts b/packages/common/src/utils.ts index bb0617e766..5e5e1e7b43 100644 --- a/packages/common/src/utils.ts +++ b/packages/common/src/utils.ts @@ -123,7 +123,7 @@ function parseGethParams(json: any, mergeForkIdPostMerge: boolean = true) { [Hardfork.London]: { name: 'londonBlock' }, [Hardfork.MergeForkIdTransition]: { name: 'mergeForkBlock', postMerge: mergeForkIdPostMerge }, [Hardfork.Shanghai]: { name: 'shanghaiTime', postMerge: true, isTimestamp: true }, - [Hardfork.ShardingForkDev]: { name: 'cancunTime', postMerge: true, isTimestamp: true }, + [Hardfork.Cancun]: { name: 'cancunTime', postMerge: true, isTimestamp: true }, } // forkMapRev is the map from config field name to Hardfork diff --git a/packages/evm/src/evm.ts b/packages/evm/src/evm.ts index 7454c305dd..557d9bf7c6 100644 --- a/packages/evm/src/evm.ts +++ b/packages/evm/src/evm.ts @@ -167,7 +167,7 @@ export class EVM implements EVMInterface { Hardfork.MergeForkIdTransition, Hardfork.Paris, Hardfork.Shanghai, - Hardfork.ShardingForkDev, + Hardfork.Cancun, ] protected _tx?: { gasPrice: bigint diff --git a/packages/evm/test/precompiles/14-pointevaluation.spec.ts b/packages/evm/test/precompiles/14-pointevaluation.spec.ts index 3e1ab41b7b..b625a90f0b 100644 --- a/packages/evm/test/precompiles/14-pointevaluation.spec.ts +++ b/packages/evm/test/precompiles/14-pointevaluation.spec.ts @@ -23,7 +23,7 @@ tape('Precompiles: point evaluation', async (t) => { const genesisJSON = require('../../../client/test/testdata/geth-genesis/eip4844.json') const common = Common.fromGethGenesis(genesisJSON, { chain: 'custom', - hardfork: Hardfork.ShardingForkDev, + hardfork: Hardfork.Cancun, }) const eei = await getEEI() const evm = await EVM.create({ common, eei }) diff --git a/packages/evm/test/runCall.spec.ts b/packages/evm/test/runCall.spec.ts index c5215ee568..ecf470db0e 100644 --- a/packages/evm/test/runCall.spec.ts +++ b/packages/evm/test/runCall.spec.ts @@ -581,7 +581,7 @@ tape('runCall() => use DATAHASH opcode from EIP 4844', async (t) => { const genesisJSON = require('../../client/test/testdata/geth-genesis/eip4844.json') const common = Common.fromGethGenesis(genesisJSON, { chain: 'custom', - hardfork: Hardfork.ShardingForkDev, + hardfork: Hardfork.Cancun, }) const eei = await getEEI() const evm = await EVM.create({ common, eei }) diff --git a/packages/tx/test/eip4844.spec.ts b/packages/tx/test/eip4844.spec.ts index 4777975bc5..779a3ed394 100644 --- a/packages/tx/test/eip4844.spec.ts +++ b/packages/tx/test/eip4844.spec.ts @@ -26,7 +26,7 @@ if (isBrowser() === false) initKZG(kzg, __dirname + '/../../client/lib/trustedSe const gethGenesis = require('../../block/test/testdata/4844-hardfork.json') const common = Common.fromGethGenesis(gethGenesis, { chain: 'customChain', - hardfork: Hardfork.ShardingForkDev, + hardfork: Hardfork.Cancun, }) tape('EIP4844 constructor tests - valid scenarios', (t) => { diff --git a/packages/vm/test/api/runTx.spec.ts b/packages/vm/test/api/runTx.spec.ts index c67e256ffd..6dff8e167e 100644 --- a/packages/vm/test/api/runTx.spec.ts +++ b/packages/vm/test/api/runTx.spec.ts @@ -891,9 +891,9 @@ tape('EIP 4844 transaction tests', async (t) => { const genesisJson = require('../../../block/test/testdata/4844-hardfork.json') const common = Common.fromGethGenesis(genesisJson, { chain: 'customChain', - hardfork: Hardfork.ShardingForkDev, + hardfork: Hardfork.Cancun, }) - common.setHardfork(Hardfork.ShardingForkDev) + common.setHardfork(Hardfork.Cancun) const oldGetBlockFunction = Blockchain.prototype.getBlock // Stub getBlock to produce a valid parent header under EIP 4844 From 11e1bff819356dd679e02534f8b88b4a2345515f Mon Sep 17 00:00:00 2001 From: acolytec3 Date: Wed, 26 Apr 2023 02:16:34 -0400 Subject: [PATCH 23/53] Fix handling of nested uint8Arrays in JSON in DB (#2666) * Fix setHeads handling of bytes in json * fix byte handling in JSON in cacheDB --- packages/blockchain/src/blockchain.ts | 8 +++++++- packages/blockchain/src/db/manager.ts | 10 ++++----- packages/blockchain/test/util.ts | 4 ++-- packages/ethash/src/index.ts | 29 ++++++++++++++++++--------- 4 files changed, 34 insertions(+), 17 deletions(-) diff --git a/packages/blockchain/src/blockchain.ts b/packages/blockchain/src/blockchain.ts index c3c366f59f..9b7280ad56 100644 --- a/packages/blockchain/src/blockchain.ts +++ b/packages/blockchain/src/blockchain.ts @@ -1211,8 +1211,14 @@ export class Blockchain implements BlockchainInterface { * @hidden */ private _saveHeadOps(): DBOp[] { + // Convert DB heads to hex strings for efficient storage in DB + // LevelDB doesn't handle Uint8Arrays properly when they are part + // of a JSON object being stored as a value in the DB + const hexHeads = Object.fromEntries( + Object.entries(this._heads).map((entry) => [entry[0], bytesToHex(entry[1])]) + ) return [ - DBOp.set(DBTarget.Heads, this._heads), + DBOp.set(DBTarget.Heads, hexHeads), DBOp.set(DBTarget.HeadHeader, this._headHeaderHash!), DBOp.set(DBTarget.HeadBlock, this._headBlockHash!), ] diff --git a/packages/blockchain/src/db/manager.ts b/packages/blockchain/src/db/manager.ts index ec099111ba..02aec83939 100644 --- a/packages/blockchain/src/db/manager.ts +++ b/packages/blockchain/src/db/manager.ts @@ -1,6 +1,7 @@ import { Block, BlockHeader, valuesArrayToHeaderData } from '@ethereumjs/block' import { RLP } from '@ethereumjs/rlp' import { KECCAK256_RLP, KECCAK256_RLP_ARRAY, bytesToBigInt, equalsBytes } from '@ethereumjs/util' +import { hexToBytes } from 'ethereum-cryptography/utils' import { Cache } from './cache' import { DBOp, DBTarget } from './operation' @@ -65,11 +66,10 @@ export class DBManager { async getHeads(): Promise<{ [key: string]: Uint8Array }> { const heads = await this.get(DBTarget.Heads) for (const key of Object.keys(heads)) { - // DB incorrectly stores the `uint8Array` representation of each head hash - // as a JSON object of key value pairs where the key is the array index - // and the value is the uint8 from that index of the original array - // so we convert it back to a Uint8Array before storing the heads - heads[key] = Uint8Array.from(Object.values(heads[key])) + // Heads are stored in DB as hex strings since Level converts Uint8Arrays + // to nested JSON objects when they are included in a value being stored + // in the DB + heads[key] = hexToBytes(heads[key]) } return heads } diff --git a/packages/blockchain/test/util.ts b/packages/blockchain/test/util.ts index 3c66a11a77..10d175c068 100644 --- a/packages/blockchain/test/util.ts +++ b/packages/blockchain/test/util.ts @@ -3,7 +3,7 @@ import { Chain, Common, Hardfork } from '@ethereumjs/common' import { RLP } from '@ethereumjs/rlp' import { toBytes } from '@ethereumjs/util' import { keccak256 } from 'ethereum-cryptography/keccak' -import { equalsBytes, hexToBytes, utf8ToBytes } from 'ethereum-cryptography/utils' +import { bytesToHex, equalsBytes, hexToBytes, utf8ToBytes } from 'ethereum-cryptography/utils' import { MemoryLevel } from 'memory-level' import { Blockchain } from '../src' @@ -179,7 +179,7 @@ export const createTestDB = async (): Promise<[Level, Block]> => { type: 'put', key: 'heads', valueEncoding: 'json', - value: { head0: [171, 205] }, + value: { head0: bytesToHex(Uint8Array.from([171, 205])) }, }, ]) return [db as any, genesis] diff --git a/packages/ethash/src/index.ts b/packages/ethash/src/index.ts index 7074101005..217f374579 100644 --- a/packages/ethash/src/index.ts +++ b/packages/ethash/src/index.ts @@ -4,12 +4,14 @@ import { TWO_POW256, bigIntToBytes, bytesToBigInt, + bytesToHex, concatBytes, equalsBytes, setLengthLeft, zeros, } from '@ethereumjs/util' import { keccak256, keccak512 } from 'ethereum-cryptography/keccak' +import { hexToBytes } from 'ethereum-cryptography/utils' import { bytesReverse, @@ -156,10 +158,10 @@ export type EthashCacheDB = AbstractLevel< string | Uint8Array, string | Uint8Array, { - cache: Uint8Array[] + cache: string[] fullSize: number cacheSize: number - seed: Uint8Array + seed: string } > @@ -302,7 +304,13 @@ export class Ethash { } let data try { - data = await this.cacheDB!.get(epoc, this.dbOpts) + const dbData = await this.cacheDB!.get(epoc, this.dbOpts) + data = { + cache: dbData.cache.map((el) => hexToBytes(el)), + fullSize: dbData.fullSize, + cacheSize: dbData.cacheSize, + seed: hexToBytes(dbData.seed), + } } catch (error: any) { if (error.code !== 'LEVEL_NOT_FOUND') { throw error @@ -317,10 +325,13 @@ export class Ethash { let data try { - data = await this.cacheDB!.get(epoc, this.dbOpts) - // Fix uint8Arrays that get stored in DB as JSON dictionary of array indices and values - data.seed = Uint8Array.from(Object.values(data.seed)) - data.cache = data.cache.map((el) => Uint8Array.from(Object.values(el))) + const dbData = await this.cacheDB!.get(epoc, this.dbOpts) + data = { + cache: dbData.cache.map((el) => hexToBytes(el)), + fullSize: dbData.fullSize, + cacheSize: dbData.cacheSize, + seed: hexToBytes(dbData.seed), + } } catch (error: any) { if (error.code !== 'LEVEL_NOT_FOUND') { throw error @@ -340,8 +351,8 @@ export class Ethash { { cacheSize: this.cacheSize, fullSize: this.fullSize, - seed: this.seed, - cache, + seed: bytesToHex(this.seed), + cache: cache.map((el) => bytesToHex(el)), }, this.dbOpts ) From cda90438b9db3b7fb82e649073747f6d4200fc65 Mon Sep 17 00:00:00 2001 From: g11tech Date: Wed, 26 Apr 2023 14:47:44 +0530 Subject: [PATCH 24/53] client: Limit blobs as per the maxDataGasPerBlock for block building (#2661) * client: Limit blobs per block as per the specs * fix blobscount accounting * refac allowedblobs limit calc * enforce blob limit while accepting blob tx * fix spec * enhance spec * log blobs included --- packages/client/lib/miner/miner.ts | 2 +- packages/client/lib/miner/pendingBlock.ts | 49 +++++++++++++--- packages/client/lib/rpc/modules/eth.ts | 11 ++++ packages/client/lib/service/txpool.ts | 40 ++++++++++--- .../client/test/miner/pendingBlock.spec.ts | 56 ++++++++++++++----- 5 files changed, 126 insertions(+), 32 deletions(-) diff --git a/packages/client/lib/miner/miner.ts b/packages/client/lib/miner/miner.ts index 578d55da7c..ba673c2e05 100644 --- a/packages/client/lib/miner/miner.ts +++ b/packages/client/lib/miner/miner.ts @@ -293,7 +293,7 @@ export class Miner { }, }) - const txs = await this.service.txPool.txsByPriceAndNonce(vmCopy, baseFeePerGas) + const txs = await this.service.txPool.txsByPriceAndNonce(vmCopy, { baseFee: baseFeePerGas }) this.config.logger.info( `Miner: Assembling block from ${txs.length} eligible txs ${ typeof baseFeePerGas === 'bigint' && baseFeePerGas !== BigInt(0) diff --git a/packages/client/lib/miner/pendingBlock.ts b/packages/client/lib/miner/pendingBlock.ts index 408ea1d800..0b8ea879e9 100644 --- a/packages/client/lib/miner/pendingBlock.ts +++ b/packages/client/lib/miner/pendingBlock.ts @@ -148,8 +148,20 @@ export class PendingBlock { this.pendingPayloads.set(payloadId, builder) + // Get if and how many blobs are allowed in the tx + let allowedBlobs + if (vm._common.isActivatedEIP(4844)) { + const dataGasLimit = vm._common.param('gasConfig', 'maxDataGasPerBlock') + const dataGasPerBlob = vm._common.param('gasConfig', 'dataGasPerBlob') + allowedBlobs = Number(dataGasLimit / dataGasPerBlob) + } else { + allowedBlobs = 0 + } // Add current txs in pool - const txs = await this.txPool.txsByPriceAndNonce(vm, baseFeePerGas) + const txs = await this.txPool.txsByPriceAndNonce(vm, { + baseFee: baseFeePerGas, + allowedBlobs, + }) this.config.logger.info( `Pending: Assembling block from ${txs.length} eligible txs (baseFee: ${baseFeePerGas})` ) @@ -225,10 +237,26 @@ export class PendingBlock { if (blockStatus.status === BuildStatus.Build) { return [blockStatus.block, builder.transactionReceipts, builder.minerValue] } - const { vm, headerData } = builder as any + const { vm, headerData } = builder as unknown as { vm: VM; headerData: HeaderData } + + // get the number of blobs that can be further added + let allowedBlobs + if (vm._common.isActivatedEIP(4844)) { + const bundle = this.blobsBundles.get(payloadId) ?? { blobs: [], commitments: [], proofs: [] } + const dataGasLimit = vm._common.param('gasConfig', 'maxDataGasPerBlock') + const dataGasPerBlob = vm._common.param('gasConfig', 'dataGasPerBlob') + allowedBlobs = Number(dataGasLimit / dataGasPerBlob) - bundle.blobs.length + } else { + allowedBlobs = 0 + } // Add new txs that the pool received - const txs = (await this.txPool.txsByPriceAndNonce(vm, headerData.baseFeePerGas)).filter( + const txs = ( + await this.txPool.txsByPriceAndNonce(vm, { + baseFee: headerData.baseFeePerGas! as bigint, + allowedBlobs, + }) + ).filter( (tx) => (builder as any).transactions.some((t: TypedTransaction) => equalsBytes(t.hash(), tx.hash()) @@ -281,18 +309,21 @@ export class PendingBlock { } const block = await builder.build() + // Construct blobs bundle + const blobs = block._common.isActivatedEIP(4844) + ? this.constructBlobsBundle(payloadId, blobTxs) + : undefined + const withdrawalsStr = block.withdrawals ? ` withdrawals=${block.withdrawals.length}` : '' + const blobsStr = blobs ? ` blobs=${blobs.blobs.length}` : '' this.config.logger.info( `Pending: Built block number=${block.header.number} txs=${ block.transactions.length - }${withdrawalsStr} skippedByAddErrors=${skippedByAddErrors} hash=${bytesToHex(block.hash())}` + }${withdrawalsStr}${blobsStr} skippedByAddErrors=${skippedByAddErrors} hash=${bytesToHex( + block.hash() + )}` ) - // Construct blobs bundle - const blobs = block._common.isActivatedEIP(4844) - ? this.constructBlobsBundle(payloadId, blobTxs) - : undefined - return [block, builder.transactionReceipts, builder.minerValue, blobs] } diff --git a/packages/client/lib/rpc/modules/eth.ts b/packages/client/lib/rpc/modules/eth.ts index 5db2cec8c2..490ce4a773 100644 --- a/packages/client/lib/rpc/modules/eth.ts +++ b/packages/client/lib/rpc/modules/eth.ts @@ -924,6 +924,17 @@ export class Eth { if (txBuf[0] === 0x03) { // Blob Transactions sent over RPC are expected to be in Network Wrapper format tx = BlobEIP4844Transaction.fromSerializedBlobTxNetworkWrapper(txBuf, { common }) + + const dataGasLimit = common.param('gasConfig', 'maxDataGasPerBlock') + const dataGasPerBlob = common.param('gasConfig', 'dataGasPerBlob') + + if (BigInt((tx.blobs ?? []).length) * dataGasPerBlob > dataGasLimit) { + throw Error( + `tx blobs=${(tx.blobs ?? []).length} exceeds block limit=${ + dataGasLimit / dataGasPerBlob + }` + ) + } } else { tx = TransactionFactory.fromSerializedData(txBuf, { common }) } diff --git a/packages/client/lib/service/txpool.ts b/packages/client/lib/service/txpool.ts index 4779cf7fd6..e9a59b261c 100644 --- a/packages/client/lib/service/txpool.ts +++ b/packages/client/lib/service/txpool.ts @@ -687,11 +687,14 @@ export class TxPool { * * @param baseFee Provide a baseFee to exclude txs with a lower gasPrice */ - async txsByPriceAndNonce(vm: VM, baseFee?: bigint) { + async txsByPriceAndNonce( + vm: VM, + { baseFee, allowedBlobs }: { baseFee?: bigint; allowedBlobs?: number } = {} + ) { const txs: TypedTransaction[] = [] // Separate the transactions by account and sort by nonce const byNonce = new Map() - const skippedStats = { byNonce: 0, byPrice: 0 } + const skippedStats = { byNonce: 0, byPrice: 0, byBlobsLimit: 0 } for (const [address, poolObjects] of this.pool) { let txsSortedByNonce = poolObjects .map((obj) => obj.tx) @@ -729,22 +732,43 @@ export class TxPool { byNonce.set(address, txs.slice(1)) } // Merge by replacing the best with the next from the same account + let blobsCount = 0 while (byPrice.length > 0) { // Retrieve the next best transaction by price const best = byPrice.remove() if (!best) break + // Push in its place the next transaction from the same account const address = best.getSenderAddress().toString().slice(2) const accTxs = byNonce.get(address)! - if (accTxs.length > 0) { - byPrice.insert(accTxs[0]) - byNonce.set(address, accTxs.slice(1)) + + // Insert the best tx into byPrice if + // i) this is not a blob tx, + // ii) or there is no blobs limit provided + // iii) or blobs are still within limit if this best tx's blobs are included + if ( + !(best instanceof BlobEIP4844Transaction) || + allowedBlobs === undefined || + ((best as BlobEIP4844Transaction).blobs ?? []).length + blobsCount <= allowedBlobs + ) { + if (accTxs.length > 0) { + byPrice.insert(accTxs[0]) + byNonce.set(address, accTxs.slice(1)) + } + // Accumulate the best priced transaction and increment blobs count + txs.push(best) + if (best instanceof BlobEIP4844Transaction) { + blobsCount += ((best as BlobEIP4844Transaction).blobs ?? []).length + } + } else { + // Since no more blobs can fit in the block, not only skip inserting in byPrice but also remove all other + // txs (blobs or not) of this sender address from further consideration + skippedStats.byBlobsLimit += 1 + accTxs.length + byNonce.set(address, []) } - // Accumulate the best priced transaction - txs.push(best) } this.config.logger.info( - `txsByPriceAndNonce selected txs=${txs.length}, skipped byNonce=${skippedStats.byNonce} byPrice=${skippedStats.byPrice}` + `txsByPriceAndNonce selected txs=${txs.length}, skipped byNonce=${skippedStats.byNonce} byPrice=${skippedStats.byPrice} byBlobsLimit=${skippedStats.byBlobsLimit}` ) return txs } diff --git a/packages/client/test/miner/pendingBlock.spec.ts b/packages/client/test/miner/pendingBlock.spec.ts index c92acd185d..890c63b47a 100644 --- a/packages/client/test/miner/pendingBlock.spec.ts +++ b/packages/client/test/miner/pendingBlock.spec.ts @@ -1,6 +1,6 @@ import { Block, BlockHeader } from '@ethereumjs/block' import { Common, Chain as CommonChain, Hardfork } from '@ethereumjs/common' -import { BlobEIP4844Transaction, Transaction } from '@ethereumjs/tx' +import { BlobEIP4844Transaction, FeeMarketEIP1559Transaction, Transaction } from '@ethereumjs/tx' import { Account, Address, @@ -275,38 +275,66 @@ tape('[PendingBlock]', async (t) => { hardfork: Hardfork.Cancun, }) const { txPool } = setup() + const blobs = getBlobs('hello world') const commitments = blobsToCommitments(blobs) const versionedHashes = commitmentsToVersionedHashes(commitments) const proofs = blobsToProofs(blobs, commitments) - const txA01 = BlobEIP4844Transaction.fromTxData( + // Create 3 txs with 2 blobs each so that only 2 of them can be included in a build + for (let x = 0; x <= 2; x++) { + const txA01 = BlobEIP4844Transaction.fromTxData( + { + versionedHashes, + blobs: [...blobs, ...blobs], + kzgCommitments: [...commitments, ...commitments], + kzgProofs: [...proofs, ...proofs], + maxFeePerDataGas: 100000000n, + gasLimit: 0xffffffn, + maxFeePerGas: 1000000000n, + maxPriorityFeePerGas: 100000000n, + to: randomBytes(20), + nonce: BigInt(x), + }, + { common } + ).sign(A.privateKey) + await txPool.add(txA01) + } + + // Add one other normal tx for nonce 3 which should also be not included in the build + const txNorm = FeeMarketEIP1559Transaction.fromTxData( { - versionedHashes, - blobs, - kzgCommitments: commitments, - kzgProofs: proofs, - maxFeePerDataGas: 100000000n, gasLimit: 0xffffffn, maxFeePerGas: 1000000000n, maxPriorityFeePerGas: 100000000n, to: randomBytes(20), + nonce: BigInt(3), }, { common } ).sign(A.privateKey) - await txPool.add(txA01) + await txPool.add(txNorm) + st.equal(txPool.txsInPool, 4, '4 txs should still be in the pool') + const pendingBlock = new PendingBlock({ config, txPool }) const vm = await VM.create({ common }) - await setBalance(vm, A.address, BigInt(5000000000000000)) + await setBalance(vm, A.address, BigInt(500000000000000000)) const parentBlock = await vm.blockchain.getCanonicalHeadBlock!() + // stub the vm's common set hf to do nothing but stay in cancun + vm._common.setHardforkByBlockNumber = (_a: bigint, _b?: bigint, _c?: bigint) => { + return vm._common.hardfork() + } const payloadId = await pendingBlock.start(vm, parentBlock) - await pendingBlock.build(payloadId) + const [block, _receipts, _value, blobsBundles] = (await pendingBlock.build(payloadId)) ?? [] + + st.ok(block !== undefined && blobsBundles !== undefined) + st.equal(block!.transactions.length, 2, 'Only two blob txs should be included') + st.equal(blobsBundles!.blobs.length, 4, 'maximum 4 blobs should be included') + st.equal(blobsBundles!.commitments.length, 4, 'maximum 4 commitments should be included') + st.equal(blobsBundles!.proofs.length, 4, 'maximum 4 proofs should be included') - const blobsBundles = pendingBlock.blobsBundles.get(bytesToPrefixedHexString(payloadId))! - st.ok(blobsBundles !== undefined) - const pendingBlob = blobsBundles.blobs[0] + const pendingBlob = blobsBundles!.blobs[0] st.ok(pendingBlob !== undefined && equalsBytes(pendingBlob, blobs[0])) - const blobProof = blobsBundles.proofs[0] + const blobProof = blobsBundles!.proofs[0] st.ok(blobProof !== undefined && equalsBytes(blobProof, proofs[0])) st.end() }) From 299843966abaad588ea048d43ef59ff89fe56840 Mon Sep 17 00:00:00 2001 From: Holger Drewes Date: Wed, 26 Apr 2023 16:45:57 +0200 Subject: [PATCH 25/53] Trie/Client: Add permanent Trie Node Cache + Client Integration (#2667) * Trie: add simple permanent LRU node cache * Cache adjustments * Trie: make cacheSize configurable, add reasonable (small) default, new CheckpointDBopts type, fix tests * Trie: switched back to 0 (deactivated) default (reduce risk of side effects), test integration * Client: integrate trie cache, trie cache size option, cache start message * Client/Trie: integrate stats * Add review suggestions --- package-lock.json | 2 + packages/client/bin/cli.ts | 6 + packages/client/lib/config.ts | 8 + packages/client/lib/execution/vmexecution.ts | 7 + packages/client/lib/types.ts | 1 + packages/trie/package.json | 1 + packages/trie/src/db/checkpoint.ts | 100 +++- packages/trie/src/trie/trie.ts | 3 +- packages/trie/src/types.ts | 20 + packages/trie/test/db/checkpoint.spec.ts | 10 +- packages/trie/test/index.spec.ts | 593 ++++++++++--------- 11 files changed, 440 insertions(+), 311 deletions(-) diff --git a/package-lock.json b/package-lock.json index 9153661555..4c8b86f565 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18210,6 +18210,7 @@ "@ethereumjs/util": "^8.0.5", "@types/readable-stream": "^2.3.13", "ethereum-cryptography": "^1.1.2", + "lru-cache": "^5.1.1", "readable-stream": "^3.6.0" }, "devDependencies": { @@ -19853,6 +19854,7 @@ "level-mem": "^6.0.1", "levelup": "^5.1.1", "lmdb": "^2.5.3", + "lru-cache": "^5.1.1", "memory-level": "^1.0.0", "micro-bmark": "0.2.0", "readable-stream": "^3.6.0" diff --git a/packages/client/bin/cli.ts b/packages/client/bin/cli.ts index 13435a388a..e1e24e43dd 100755 --- a/packages/client/bin/cli.ts +++ b/packages/client/bin/cli.ts @@ -253,6 +253,11 @@ const args: ClientOpts = yargs(hideBin(process.argv)) number: true, default: Config.STORAGE_CACHE, }) + .option('trieCache', { + describe: 'Size for the trie cache (max number of trie nodes)', + number: true, + default: Config.TRIE_CACHE, + }) .option('debugCode', { describe: 'Generate code for local debugging (internal usage mostly)', boolean: true, @@ -733,6 +738,7 @@ async function run() { numBlocksPerIteration: args.numBlocksPerIteration, accountCache: args.accountCache, storageCache: args.storageCache, + trieCache: args.trieCache, dnsNetworks: args.dnsNetworks, extIP: args.extIP, key, diff --git a/packages/client/lib/config.ts b/packages/client/lib/config.ts index 47378c5e24..da21081bda 100644 --- a/packages/client/lib/config.ts +++ b/packages/client/lib/config.ts @@ -203,6 +203,11 @@ export interface ConfigOptions { */ storageCache?: number + /** + * Size for the trie cache (max number of trie nodes) + */ + trieCache?: number + /** * Generate code for local debugging, currently providing a * code snippet which can be used to run blocks on the @@ -307,6 +312,7 @@ export class Config { public static readonly NUM_BLOCKS_PER_ITERATION = 50 public static readonly ACCOUNT_CACHE = 1000000 public static readonly STORAGE_CACHE = 200000 + public static readonly TRIE_CACHE = 500000 public static readonly DEBUGCODE_DEFAULT = false public static readonly SAFE_REORG_DISTANCE = 100 public static readonly SKELETON_FILL_CANONICAL_BACKSTEP = 100 @@ -341,6 +347,7 @@ export class Config { public readonly numBlocksPerIteration: number public readonly accountCache: number public readonly storageCache: number + public readonly trieCache: number public readonly debugCode: boolean public readonly discDns: boolean public readonly discV4: boolean @@ -397,6 +404,7 @@ export class Config { this.numBlocksPerIteration = options.numBlocksPerIteration ?? Config.NUM_BLOCKS_PER_ITERATION this.accountCache = options.accountCache ?? Config.ACCOUNT_CACHE this.storageCache = options.storageCache ?? Config.STORAGE_CACHE + this.trieCache = options.trieCache ?? Config.TRIE_CACHE this.debugCode = options.debugCode ?? Config.DEBUGCODE_DEFAULT this.mine = options.mine ?? false this.isSingleNode = options.isSingleNode ?? false diff --git a/packages/client/lib/execution/vmexecution.ts b/packages/client/lib/execution/vmexecution.ts index 6e3cddc8a9..297c13b766 100644 --- a/packages/client/lib/execution/vmexecution.ts +++ b/packages/client/lib/execution/vmexecution.ts @@ -51,10 +51,12 @@ export class VMExecution extends Execution { const trie = new Trie({ db: new LevelDB(this.stateDB), useKeyHashing: true, + cacheSize: this.config.trieCache, }) this.config.logger.info(`Initializing account cache size=${this.config.accountCache}`) this.config.logger.info(`Initializing storage cache size=${this.config.storageCache}`) + this.config.logger.info(`Initializing trie cache size=${this.config.trieCache}`) const stateManager = new DefaultStateManager({ trie, accountCacheOpts: { @@ -574,6 +576,11 @@ export class VMExecution extends Execution { this.config.logger.info( `Storage cache stats size=${stats.size} reads=${stats.reads} hits=${stats.hits} writes=${stats.writes}` ) + const tStats = ((vm.stateManager as any)._trie as Trie).database().stats() + this.config.logger.info( + `Trie cache stats size=${tStats.size} reads=${tStats.cache.reads} hits=${tStats.cache.hits} ` + + `writes=${tStats.cache.writes} readsDB=${tStats.db.reads} hitsDB=${tStats.db.hits} writesDB=${tStats.db.writes}` + ) this.cacheStatsCount = 0 } } diff --git a/packages/client/lib/types.ts b/packages/client/lib/types.ts index db85ebc942..b2be86c8cf 100644 --- a/packages/client/lib/types.ts +++ b/packages/client/lib/types.ts @@ -146,6 +146,7 @@ export interface ClientOpts { numBlocksPerIteration?: number accountCache?: number storageCache?: number + trieCache?: number dnsNetworks?: string[] executeBlocks?: string debugCode?: boolean diff --git a/packages/trie/package.json b/packages/trie/package.json index df98d20188..cd054e0c50 100644 --- a/packages/trie/package.json +++ b/packages/trie/package.json @@ -49,6 +49,7 @@ "@ethereumjs/util": "^8.0.5", "@types/readable-stream": "^2.3.13", "ethereum-cryptography": "^1.1.2", + "lru-cache": "^5.1.1", "readable-stream": "^3.6.0" }, "devDependencies": { diff --git a/packages/trie/src/db/checkpoint.ts b/packages/trie/src/db/checkpoint.ts index 26c13e101f..6d033a5aae 100644 --- a/packages/trie/src/db/checkpoint.ts +++ b/packages/trie/src/db/checkpoint.ts @@ -1,6 +1,9 @@ import { bytesToHex, hexStringToBytes } from '@ethereumjs/util' -import type { BatchDBOp, Checkpoint, DB } from '../types' +import type { BatchDBOp, Checkpoint, CheckpointDBOpts, DB } from '../types' +import type LRUCache from 'lru-cache' + +const LRU = require('lru-cache') /** * DB is a thin wrapper around the underlying levelup db, @@ -9,14 +12,38 @@ import type { BatchDBOp, Checkpoint, DB } from '../types' export class CheckpointDB implements DB { public checkpoints: Checkpoint[] public db: DB + public readonly cacheSize: number + + protected _cache?: LRUCache + + _stats = { + cache: { + reads: 0, + hits: 0, + writes: 0, + }, + db: { + reads: 0, + hits: 0, + writes: 0, + }, + } /** * Initialize a DB instance. */ - constructor(db: DB) { - this.db = db + constructor(opts: CheckpointDBOpts) { + this.db = opts.db + this.cacheSize = opts.cacheSize ?? 0 // Roots of trie at the moment of checkpoint this.checkpoints = [] + + if (this.cacheSize > 0) { + this._cache = new LRU({ + max: this.cacheSize, + updateAgeOnGet: true, + }) + } } /** @@ -73,7 +100,7 @@ export class CheckpointDB implements DB { } await this.batch(batchOp) } else { - // dump everything into the current (higher level) cache + // dump everything into the current (higher level) diff cache const currentKeyValueMap = this.checkpoints[this.checkpoints.length - 1].keyValueMap for (const [key, value] of keyValueMap.entries()) { currentKeyValueMap.set(key, value) @@ -93,18 +120,33 @@ export class CheckpointDB implements DB { * @inheritDoc */ async get(key: Uint8Array): Promise { - // Lookup the value in our cache. We return the latest checkpointed value (which should be the value on disk) + const keyHex = bytesToHex(key) + if (this._cache !== undefined) { + const value = this._cache.get(keyHex) + this._stats.cache.reads += 1 + if (value !== undefined) { + this._stats.cache.hits += 1 + return value + } + } + + // Lookup the value in our diff cache. We return the latest checkpointed value (which should be the value on disk) for (let index = this.checkpoints.length - 1; index >= 0; index--) { const value = this.checkpoints[index].keyValueMap.get(bytesToHex(key)) if (value !== undefined) { return value } } - // Nothing has been found in cache, look up from disk - + // Nothing has been found in diff cache, look up from disk const value = await this.db.get(key) + this._stats.db.reads += 1 + if (value !== null) { + this._stats.db.hits += 1 + } + this._cache?.set(keyHex, value) if (this.hasCheckpoints()) { - // Since we are a checkpoint, put this value in cache, so future `get` calls will not look the key up again from disk. + // Since we are a checkpoint, put this value in diff cache, + // so future `get` calls will not look the key up again from disk. this.checkpoints[this.checkpoints.length - 1].keyValueMap.set(bytesToHex(key), value) } @@ -114,12 +156,18 @@ export class CheckpointDB implements DB { /** * @inheritDoc */ - async put(key: Uint8Array, val: Uint8Array): Promise { + async put(key: Uint8Array, value: Uint8Array): Promise { + const keyHex = bytesToHex(key) + if (this._cache !== undefined) { + this._cache.set(keyHex, value) + this._stats.cache.writes += 1 + } if (this.hasCheckpoints()) { - // put value in cache - this.checkpoints[this.checkpoints.length - 1].keyValueMap.set(bytesToHex(key), val) + // put value in diff cache + this.checkpoints[this.checkpoints.length - 1].keyValueMap.set(bytesToHex(key), value) } else { - await this.db.put(key, val) + await this.db.put(key, value) + this._stats.db.writes += 1 } } @@ -127,8 +175,13 @@ export class CheckpointDB implements DB { * @inheritDoc */ async del(key: Uint8Array): Promise { + const keyHex = bytesToHex(key) + if (this._cache !== undefined) { + this._cache.set(keyHex, null) + this._stats.cache.writes += 1 + } if (this.hasCheckpoints()) { - // delete the value in the current cache + // delete the value in the current diff cache this.checkpoints[this.checkpoints.length - 1].keyValueMap.set(bytesToHex(key), null) } else { // delete the value on disk @@ -153,10 +206,29 @@ export class CheckpointDB implements DB { } } + stats(reset = true) { + const stats = { ...this._stats, size: this._cache?.length ?? 0 } + if (reset) { + this._stats = { + cache: { + reads: 0, + hits: 0, + writes: 0, + }, + db: { + reads: 0, + hits: 0, + writes: 0, + }, + } + } + return stats + } + /** * @inheritDoc */ copy(): CheckpointDB { - return new CheckpointDB(this.db) + return new CheckpointDB({ db: this.db, cacheSize: this.cacheSize }) } } diff --git a/packages/trie/src/trie/trie.ts b/packages/trie/src/trie/trie.ts index 19e5fd4d33..6c01279958 100644 --- a/packages/trie/src/trie/trie.ts +++ b/packages/trie/src/trie/trie.ts @@ -39,6 +39,7 @@ export class Trie { useKeyHashingFunction: keccak256, useRootPersistence: false, useNodePruning: false, + cacheSize: 0, } /** The root for an empty trie */ @@ -96,7 +97,7 @@ export class Trie { throw new Error('Cannot pass in an instance of CheckpointDB') } - this._db = new CheckpointDB(db) + this._db = new CheckpointDB({ db, cacheSize: this._opts.cacheSize }) } return this._db diff --git a/packages/trie/src/types.ts b/packages/trie/src/types.ts index 68cb4cd0c0..d267e847e6 100644 --- a/packages/trie/src/types.ts +++ b/packages/trie/src/types.ts @@ -62,6 +62,13 @@ export interface TrieOpts { * unreachable nodes will be pruned (deleted) from the trie */ useNodePruning?: boolean + + /** + * LRU cache for trie nodes to allow for faster node retrieval. + * + * Default: 0 (deactivated) + */ + cacheSize?: number } export type TrieOptsWithDefaults = TrieOpts & { @@ -69,6 +76,19 @@ export type TrieOptsWithDefaults = TrieOpts & { useKeyHashingFunction: HashKeysFunction useRootPersistence: boolean useNodePruning: boolean + cacheSize: number +} + +export interface CheckpointDBOpts { + /** + * A database instance. + */ + db: DB + + /** + * Cache size (default: 0) + */ + cacheSize?: number } export type BatchDBOp = PutBatch | DelBatch diff --git a/packages/trie/test/db/checkpoint.spec.ts b/packages/trie/test/db/checkpoint.spec.ts index 8514d2078b..02d4129939 100644 --- a/packages/trie/test/db/checkpoint.spec.ts +++ b/packages/trie/test/db/checkpoint.spec.ts @@ -12,7 +12,7 @@ tape('DB tests', (t) => { const v3 = utf8ToBytes('v3') t.test('Checkpointing: revert -> put (add)', async (st) => { - const db = new CheckpointDB(new MapDB()) + const db = new CheckpointDB({ db: new MapDB() }) db.checkpoint(hexStringToBytes('01')) await db.put(k, v) st.deepEqual(await db.get(k), v, 'before revert: v1') @@ -22,7 +22,7 @@ tape('DB tests', (t) => { }) t.test('Checkpointing: revert -> put (update)', async (st) => { - const db = new CheckpointDB(new MapDB()) + const db = new CheckpointDB({ db: new MapDB() }) await db.put(k, v) st.deepEqual(await db.get(k), v, 'before CP: v1') db.checkpoint(hexStringToBytes('01')) @@ -34,7 +34,7 @@ tape('DB tests', (t) => { }) t.test('Checkpointing: revert -> put (update) batched', async (st) => { - const db = new CheckpointDB(new MapDB()) + const db = new CheckpointDB({ db: new MapDB() }) await db.put(k, v) st.deepEqual(await db.get(k), v, 'before CP: v1') db.checkpoint(hexStringToBytes('01')) @@ -49,7 +49,7 @@ tape('DB tests', (t) => { }) t.test('Checkpointing: revert -> del', async (st) => { - const db = new CheckpointDB(new MapDB()) + const db = new CheckpointDB({ db: new MapDB() }) await db.put(k, v) st.deepEqual(await db.get(k), v, 'before CP: v1') db.checkpoint(hexStringToBytes('01')) @@ -61,7 +61,7 @@ tape('DB tests', (t) => { }) t.test('Checkpointing: nested checkpoints -> commit -> revert', async (st) => { - const db = new CheckpointDB(new MapDB()) + const db = new CheckpointDB({ db: new MapDB() }) await db.put(k, v) st.deepEqual(await db.get(k), v, 'before CP: v1') diff --git a/packages/trie/test/index.spec.ts b/packages/trie/test/index.spec.ts index 65b7ab0544..bc34319b13 100644 --- a/packages/trie/test/index.spec.ts +++ b/packages/trie/test/index.spec.ts @@ -16,355 +16,366 @@ import { bytesToNibbles } from '../src/util/nibbles' import type { HashKeysFunction } from '../src' -tape('simple save and retrieve', function (tester) { - const it = tester.test - - it('should not crash if given a non-existent root', async function (t) { - const root = hexStringToBytes( - '3f4399b08efe68945c1cf90ffe85bbe3ce978959da753f9e649f034015b8817d' - ) - - const trie = new Trie({ root }) - const value = await trie.get(utf8ToBytes('test')) - t.equal(value, null) - t.end() - }) - - const trie = new Trie() - - it('save a value', async function (t) { - await trie.put(utf8ToBytes('test'), utf8ToBytes('one')) - t.end() - }) - - it('should get a value', async function (t) { - const value = await trie.get(utf8ToBytes('test')) - t.equal(bytesToUtf8(value!), 'one') - t.end() - }) - - it('should update a value', async function (t) { - await trie.put(utf8ToBytes('test'), utf8ToBytes('two')) - const value = await trie.get(utf8ToBytes('test')) - - t.equal(bytesToUtf8(value!), 'two') - t.end() - }) - - it('should delete a value', async function (t) { - await trie.del(utf8ToBytes('test')) - const value = await trie.get(utf8ToBytes('test')) - t.notok(value) - t.end() - }) +for (const cacheSize of [0, 100]) { + tape('simple save and retrieve', function (tester) { + const it = tester.test - it('should recreate a value', async function (t) { - await trie.put(utf8ToBytes('test'), utf8ToBytes('one')) - t.end() - }) + it('should not crash if given a non-existent root', async function (t) { + const root = hexStringToBytes( + '3f4399b08efe68945c1cf90ffe85bbe3ce978959da753f9e649f034015b8817d' + ) - it('should get updated a value', async function (t) { - const value = await trie.get(utf8ToBytes('test')) - t.equal(bytesToUtf8(value!), 'one') - t.end() - }) + const trie = new Trie({ root }) + const value = await trie.get(utf8ToBytes('test')) + t.equal(value, null) + t.end() + }) - it('should create a branch here', async function (t) { - await trie.put(utf8ToBytes('doge'), utf8ToBytes('coin')) - t.equal( - 'de8a34a8c1d558682eae1528b47523a483dd8685d6db14b291451a66066bf0fc', - bytesToHex(trie.root()) - ) - t.end() - }) + const trie = new Trie({ cacheSize }) - it('should get a value that is in a branch', async function (t) { - const value = await trie.get(utf8ToBytes('doge')) - t.equal(bytesToUtf8(value!), 'coin') - t.end() - }) + it('save a value', async function (t) { + await trie.put(utf8ToBytes('test'), utf8ToBytes('one')) + t.end() + }) - it('should delete from a branch', async function (t) { - await trie.del(utf8ToBytes('doge')) - const value = await trie.get(utf8ToBytes('doge')) - t.equal(value, null) - t.end() - }) + it('should get a value', async function (t) { + const value = await trie.get(utf8ToBytes('test')) + t.equal(bytesToUtf8(value!), 'one') + t.end() + }) - tape('storing longer values', async function (tester) { - const it = tester.test - const trie = new Trie() - const longString = 'this will be a really really really long value' - const longStringRoot = 'b173e2db29e79c78963cff5196f8a983fbe0171388972106b114ef7f5c24dfa3' + it('should update a value', async function (t) { + await trie.put(utf8ToBytes('test'), utf8ToBytes('two')) + const value = await trie.get(utf8ToBytes('test')) - it('should store a longer string', async function (t) { - await trie.put(utf8ToBytes('done'), utf8ToBytes(longString)) - await trie.put(utf8ToBytes('doge'), utf8ToBytes('coin')) - t.equal(longStringRoot, bytesToHex(trie.root())) + t.equal(bytesToUtf8(value!), 'two') t.end() }) - it('should retrieve a longer value', async function (t) { - const value = await trie.get(utf8ToBytes('done')) - t.equal(bytesToUtf8(value!), longString) + it('should delete a value', async function (t) { + await trie.del(utf8ToBytes('test')) + const value = await trie.get(utf8ToBytes('test')) + t.notok(value) t.end() }) - it('should when being modified delete the old value', async function (t) { - await trie.put(utf8ToBytes('done'), utf8ToBytes('test')) + it('should recreate a value', async function (t) { + await trie.put(utf8ToBytes('test'), utf8ToBytes('one')) t.end() }) - }) - tape('testing extensions and branches', function (tester) { - const it = tester.test - const trie = new Trie() - - it('should store a value', async function (t) { - await trie.put(utf8ToBytes('doge'), utf8ToBytes('coin')) + it('should get updated a value', async function (t) { + const value = await trie.get(utf8ToBytes('test')) + t.equal(bytesToUtf8(value!), 'one') t.end() }) - it('should create extension to store this value', async function (t) { - await trie.put(utf8ToBytes('do'), utf8ToBytes('verb')) + it('should create a branch here', async function (t) { + await trie.put(utf8ToBytes('doge'), utf8ToBytes('coin')) t.equal( - 'f803dfcb7e8f1afd45e88eedb4699a7138d6c07b71243d9ae9bff720c99925f9', + 'de8a34a8c1d558682eae1528b47523a483dd8685d6db14b291451a66066bf0fc', bytesToHex(trie.root()) ) t.end() }) - it('should store this value under the extension', async function (t) { - await trie.put(utf8ToBytes('done'), utf8ToBytes('finished')) - t.equal( - '409cff4d820b394ed3fb1cd4497bdd19ffa68d30ae34157337a7043c94a3e8cb', - bytesToHex(trie.root()) - ) + it('should get a value that is in a branch', async function (t) { + const value = await trie.get(utf8ToBytes('doge')) + t.equal(bytesToUtf8(value!), 'coin') + t.end() + }) + + it('should delete from a branch', async function (t) { + await trie.del(utf8ToBytes('doge')) + const value = await trie.get(utf8ToBytes('doge')) + t.equal(value, null) t.end() }) + + tape('storing longer values', async function (tester) { + const it = tester.test + const trie = new Trie({ cacheSize }) + const longString = 'this will be a really really really long value' + const longStringRoot = 'b173e2db29e79c78963cff5196f8a983fbe0171388972106b114ef7f5c24dfa3' + + it('should store a longer string', async function (t) { + await trie.put(utf8ToBytes('done'), utf8ToBytes(longString)) + await trie.put(utf8ToBytes('doge'), utf8ToBytes('coin')) + t.equal(longStringRoot, bytesToHex(trie.root())) + t.end() + }) + + it('should retrieve a longer value', async function (t) { + const value = await trie.get(utf8ToBytes('done')) + t.equal(bytesToUtf8(value!), longString) + t.end() + }) + + it('should when being modified delete the old value', async function (t) { + await trie.put(utf8ToBytes('done'), utf8ToBytes('test')) + t.end() + }) + }) + + tape('testing extensions and branches', function (tester) { + const it = tester.test + const trie = new Trie({ cacheSize }) + + it('should store a value', async function (t) { + await trie.put(utf8ToBytes('doge'), utf8ToBytes('coin')) + t.end() + }) + + it('should create extension to store this value', async function (t) { + await trie.put(utf8ToBytes('do'), utf8ToBytes('verb')) + t.equal( + 'f803dfcb7e8f1afd45e88eedb4699a7138d6c07b71243d9ae9bff720c99925f9', + bytesToHex(trie.root()) + ) + t.end() + }) + + it('should store this value under the extension', async function (t) { + await trie.put(utf8ToBytes('done'), utf8ToBytes('finished')) + t.equal( + '409cff4d820b394ed3fb1cd4497bdd19ffa68d30ae34157337a7043c94a3e8cb', + bytesToHex(trie.root()) + ) + t.end() + }) + }) + + tape('testing extensions and branches - reverse', function (tester) { + const it = tester.test + const trie = new Trie({ cacheSize }) + + it('should create extension to store this value', async function (t) { + await trie.put(utf8ToBytes('do'), utf8ToBytes('verb')) + t.end() + }) + + it('should store a value', async function (t) { + await trie.put(utf8ToBytes('doge'), utf8ToBytes('coin')) + t.end() + }) + + it('should store this value under the extension', async function (t) { + await trie.put(utf8ToBytes('done'), utf8ToBytes('finished')) + t.equal( + '409cff4d820b394ed3fb1cd4497bdd19ffa68d30ae34157337a7043c94a3e8cb', + bytesToHex(trie.root()) + ) + t.end() + }) + }) }) - tape('testing extensions and branches - reverse', function (tester) { + tape('testing deletion cases', function (tester) { const it = tester.test - const trie = new Trie() + const trieSetup = { + trie: new Trie({ cacheSize }), + msg: 'without DB delete', + } - it('should create extension to store this value', async function (t) { - await trie.put(utf8ToBytes('do'), utf8ToBytes('verb')) + it('should delete from a branch->branch-branch', async function (t) { + await trieSetup.trie.put(new Uint8Array([11, 11, 11]), utf8ToBytes('first')) + await trieSetup.trie.put(new Uint8Array([12, 22, 22]), utf8ToBytes('create the first branch')) + await trieSetup.trie.put(new Uint8Array([12, 34, 44]), utf8ToBytes('create the last branch')) + + await trieSetup.trie.del(new Uint8Array([12, 22, 22])) + const val = await trieSetup.trie.get(new Uint8Array([12, 22, 22])) + t.equal(null, val, trieSetup.msg) t.end() }) - it('should store a value', async function (t) { - await trie.put(utf8ToBytes('doge'), utf8ToBytes('coin')) + it('should delete from a branch->branch-extension', async function (t) { + await trieSetup.trie.put(new Uint8Array([11, 11, 11]), utf8ToBytes('first')) + await trieSetup.trie.put(new Uint8Array([12, 22, 22]), utf8ToBytes('create the first branch')) + await trieSetup.trie.put( + new Uint8Array([12, 33, 33]), + utf8ToBytes('create the middle branch') + ) + await trieSetup.trie.put(new Uint8Array([12, 34, 44]), utf8ToBytes('create the last branch')) + + await trieSetup.trie.del(new Uint8Array([12, 22, 22])) + const val = await trieSetup.trie.get(new Uint8Array([12, 22, 22])) + t.equal(null, val, trieSetup.msg) + t.end() }) - it('should store this value under the extension', async function (t) { - await trie.put(utf8ToBytes('done'), utf8ToBytes('finished')) - t.equal( - '409cff4d820b394ed3fb1cd4497bdd19ffa68d30ae34157337a7043c94a3e8cb', - bytesToHex(trie.root()) + it('should delete from a extension->branch-extension', async function (t) { + await trieSetup.trie.put(new Uint8Array([11, 11, 11]), utf8ToBytes('first')) + await trieSetup.trie.put(new Uint8Array([12, 22, 22]), utf8ToBytes('create the first branch')) + await trieSetup.trie.put( + new Uint8Array([12, 33, 33]), + utf8ToBytes('create the middle branch') ) + await trieSetup.trie.put(new Uint8Array([12, 34, 44]), utf8ToBytes('create the last branch')) + + // delete the middle branch + await trieSetup.trie.del(new Uint8Array([11, 11, 11])) + const val = await trieSetup.trie.get(new Uint8Array([11, 11, 11])) + t.equal(null, val, trieSetup.msg) + + t.end() + }) + + it('should delete from a extension->branch-branch', async function (t) { + await trieSetup.trie.put(new Uint8Array([11, 11, 11]), utf8ToBytes('first')) + await trieSetup.trie.put(new Uint8Array([12, 22, 22]), utf8ToBytes('create the first branch')) + await trieSetup.trie.put( + new Uint8Array([12, 33, 33]), + utf8ToBytes('create the middle branch') + ) + await trieSetup.trie.put(new Uint8Array([12, 34, 44]), utf8ToBytes('create the last branch')) + // delete the middle branch + await trieSetup.trie.del(new Uint8Array([11, 11, 11])) + const val = await trieSetup.trie.get(new Uint8Array([11, 11, 11])) + t.equal(null, val, trieSetup.msg) + t.end() }) - }) -}) - -tape('testing deletion cases', function (tester) { - const it = tester.test - const trieSetup = { - trie: new Trie(), - msg: 'without DB delete', - } - - it('should delete from a branch->branch-branch', async function (t) { - await trieSetup.trie.put(new Uint8Array([11, 11, 11]), utf8ToBytes('first')) - await trieSetup.trie.put(new Uint8Array([12, 22, 22]), utf8ToBytes('create the first branch')) - await trieSetup.trie.put(new Uint8Array([12, 34, 44]), utf8ToBytes('create the last branch')) - - await trieSetup.trie.del(new Uint8Array([12, 22, 22])) - const val = await trieSetup.trie.get(new Uint8Array([12, 22, 22])) - t.equal(null, val, trieSetup.msg) - t.end() }) - it('should delete from a branch->branch-extension', async function (t) { - await trieSetup.trie.put(new Uint8Array([11, 11, 11]), utf8ToBytes('first')) - await trieSetup.trie.put(new Uint8Array([12, 22, 22]), utf8ToBytes('create the first branch')) - await trieSetup.trie.put(new Uint8Array([12, 33, 33]), utf8ToBytes('create the middle branch')) - await trieSetup.trie.put(new Uint8Array([12, 34, 44]), utf8ToBytes('create the last branch')) + tape('shall handle the case of node not found correctly', async (t) => { + const trie = new Trie({ cacheSize }) + await trie.put(utf8ToBytes('a'), utf8ToBytes('value1')) + await trie.put(utf8ToBytes('aa'), utf8ToBytes('value2')) + await trie.put(utf8ToBytes('aaa'), utf8ToBytes('value3')) - await trieSetup.trie.del(new Uint8Array([12, 22, 22])) - const val = await trieSetup.trie.get(new Uint8Array([12, 22, 22])) - t.equal(null, val, trieSetup.msg) + /* Setups a trie which consists of + ExtensionNode -> + BranchNode -> value1 + ExtensionNode -> + BranchNode -> value2 + LeafNode -> value3 + */ - t.end() - }) + let path = await trie.findPath(utf8ToBytes('aaa')) - it('should delete from a extension->branch-extension', async function (t) { - await trieSetup.trie.put(new Uint8Array([11, 11, 11]), utf8ToBytes('first')) - await trieSetup.trie.put(new Uint8Array([12, 22, 22]), utf8ToBytes('create the first branch')) - await trieSetup.trie.put(new Uint8Array([12, 33, 33]), utf8ToBytes('create the middle branch')) - await trieSetup.trie.put(new Uint8Array([12, 34, 44]), utf8ToBytes('create the last branch')) + t.ok(path.node !== null, 'findPath should find a node') - // delete the middle branch - await trieSetup.trie.del(new Uint8Array([11, 11, 11])) - const val = await trieSetup.trie.get(new Uint8Array([11, 11, 11])) - t.equal(null, val, trieSetup.msg) + const { stack } = await trie.findPath(utf8ToBytes('aaa')) + // @ts-expect-error + await trie._db.del(keccak256(stack[1].serialize())) // delete the BranchNode -> value1 from the DB - t.end() - }) + path = await trie.findPath(utf8ToBytes('aaa')) - it('should delete from a extension->branch-branch', async function (t) { - await trieSetup.trie.put(new Uint8Array([11, 11, 11]), utf8ToBytes('first')) - await trieSetup.trie.put(new Uint8Array([12, 22, 22]), utf8ToBytes('create the first branch')) - await trieSetup.trie.put(new Uint8Array([12, 33, 33]), utf8ToBytes('create the middle branch')) - await trieSetup.trie.put(new Uint8Array([12, 34, 44]), utf8ToBytes('create the last branch')) - // delete the middle branch - await trieSetup.trie.del(new Uint8Array([11, 11, 11])) - const val = await trieSetup.trie.get(new Uint8Array([11, 11, 11])) - t.equal(null, val, trieSetup.msg) + t.ok(path.node === null, 'findPath should not return a node now') + t.ok( + path.stack.length === 1, + 'findPath should find the first extension node which is still in the DB' + ) t.end() }) -}) - -tape('shall handle the case of node not found correctly', async (t) => { - const trie = new Trie() - await trie.put(utf8ToBytes('a'), utf8ToBytes('value1')) - await trie.put(utf8ToBytes('aa'), utf8ToBytes('value2')) - await trie.put(utf8ToBytes('aaa'), utf8ToBytes('value3')) - - /* Setups a trie which consists of - ExtensionNode -> - BranchNode -> value1 - ExtensionNode -> - BranchNode -> value2 - LeafNode -> value3 - */ - - let path = await trie.findPath(utf8ToBytes('aaa')) - - t.ok(path.node !== null, 'findPath should find a node') - - const { stack } = await trie.findPath(utf8ToBytes('aaa')) - // @ts-expect-error - await trie._db.del(keccak256(stack[1].serialize())) // delete the BranchNode -> value1 from the DB - - path = await trie.findPath(utf8ToBytes('aaa')) - - t.ok(path.node === null, 'findPath should not return a node now') - t.ok( - path.stack.length === 1, - 'findPath should find the first extension node which is still in the DB' - ) - - t.end() -}) - -tape('it should create the genesis state root from ethereum', function (tester) { - const it = tester.test - const trie4 = new Trie() - - const g = hexStringToBytes('8a40bfaa73256b60764c1bf40675a99083efb075') - const j = hexStringToBytes('e6716f9544a56c530d868e4bfbacb172315bdead') - const v = hexStringToBytes('1e12515ce3e0f817a4ddef9ca55788a1d66bd2df') - const a = hexStringToBytes('1a26338f0d905e295fccb71fa9ea849ffa12aaf4') - - const storageRoot = new Uint8Array(32) - storageRoot.fill(0) - - const startAmount = new Uint8Array(26) - startAmount.fill(0) - startAmount[0] = 1 - - const account = [startAmount, 0, storageRoot, KECCAK256_NULL] - const rlpAccount = RLP.encode(account) - const cppRlp = - 'f85e9a010000000000000000000000000000000000000000000000000080a00000000000000000000000000000000000000000000000000000000000000000a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470' - - const genesisStateRoot = '2f4399b08efe68945c1cf90ffe85bbe3ce978959da753f9e649f034015b8817d' - tester.equal(cppRlp, bytesToHex(rlpAccount)) - - it('shall match the root', async function (t) { - await trie4.put(g, rlpAccount) - await trie4.put(j, rlpAccount) - await trie4.put(v, rlpAccount) - await trie4.put(a, rlpAccount) - t.equal(bytesToHex(trie4.root()), genesisStateRoot) + + tape('it should create the genesis state root from ethereum', function (tester) { + const it = tester.test + const trie4 = new Trie({ cacheSize }) + + const g = hexStringToBytes('8a40bfaa73256b60764c1bf40675a99083efb075') + const j = hexStringToBytes('e6716f9544a56c530d868e4bfbacb172315bdead') + const v = hexStringToBytes('1e12515ce3e0f817a4ddef9ca55788a1d66bd2df') + const a = hexStringToBytes('1a26338f0d905e295fccb71fa9ea849ffa12aaf4') + + const storageRoot = new Uint8Array(32) + storageRoot.fill(0) + + const startAmount = new Uint8Array(26) + startAmount.fill(0) + startAmount[0] = 1 + + const account = [startAmount, 0, storageRoot, KECCAK256_NULL] + const rlpAccount = RLP.encode(account) + const cppRlp = + 'f85e9a010000000000000000000000000000000000000000000000000080a00000000000000000000000000000000000000000000000000000000000000000a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470' + + const genesisStateRoot = '2f4399b08efe68945c1cf90ffe85bbe3ce978959da753f9e649f034015b8817d' + tester.equal(cppRlp, bytesToHex(rlpAccount)) + + it('shall match the root', async function (t) { + await trie4.put(g, rlpAccount) + await trie4.put(j, rlpAccount) + await trie4.put(v, rlpAccount) + await trie4.put(a, rlpAccount) + t.equal(bytesToHex(trie4.root()), genesisStateRoot) + t.end() + }) + }) + + tape('setting back state root (deleteFromDB)', async (t) => { + const k1 = utf8ToBytes('1') + /* Testing with longer value due to `rlpNode.length >= 32` check in `_formatNode()` + * Reasoning from https://ethereum.org/en/developers/docs/data-structures-and-encoding/patricia-merkle-trie/: + * "When one node is referenced inside another node, what is included is `H(rlp.encode(x))`, + * where `H(x) = sha3(x) if len(x) >= 32 else x`" + */ + const v1 = utf8ToBytes('this-is-some-longer-value-to-test-the-delete-operation-value1') + const k2 = utf8ToBytes('2') + const v2 = utf8ToBytes('this-is-some-longer-value-to-test-the-delete-operation-value2') + + const rootAfterK1 = hexStringToBytes( + '809e75931f394603657e113eb7244794f35b8d326cff99407111d600722e9425' + ) + + const trieSetup = { + trie: new Trie({ cacheSize }), + expected: v1, + msg: 'should return v1 when setting back the state root when deleteFromDB=false', + } + + await trieSetup.trie.put(k1, v1) + await trieSetup.trie.put(k2, v2) + await trieSetup.trie.del(k1) + t.equal( + await trieSetup.trie.get(k1), + null, + 'should return null on latest state root independently from deleteFromDB setting' + ) + + trieSetup.trie.root(rootAfterK1) + t.deepEqual(await trieSetup.trie.get(k1), trieSetup.expected, trieSetup.msg) + t.end() }) -}) - -tape('setting back state root (deleteFromDB)', async (t) => { - const k1 = utf8ToBytes('1') - /* Testing with longer value due to `rlpNode.length >= 32` check in `_formatNode()` - * Reasoning from https://ethereum.org/en/developers/docs/data-structures-and-encoding/patricia-merkle-trie/: - * "When one node is referenced inside another node, what is included is `H(rlp.encode(x))`, - * where `H(x) = sha3(x) if len(x) >= 32 else x`" - */ - const v1 = utf8ToBytes('this-is-some-longer-value-to-test-the-delete-operation-value1') - const k2 = utf8ToBytes('2') - const v2 = utf8ToBytes('this-is-some-longer-value-to-test-the-delete-operation-value2') - - const rootAfterK1 = hexStringToBytes( - '809e75931f394603657e113eb7244794f35b8d326cff99407111d600722e9425' - ) - - const trieSetup = { - trie: new Trie(), - expected: v1, - msg: 'should return v1 when setting back the state root when deleteFromDB=false', - } - - await trieSetup.trie.put(k1, v1) - await trieSetup.trie.put(k2, v2) - await trieSetup.trie.del(k1) - t.equal( - await trieSetup.trie.get(k1), - null, - 'should return null on latest state root independently from deleteFromDB setting' - ) - - trieSetup.trie.root(rootAfterK1) - t.deepEqual(await trieSetup.trie.get(k1), trieSetup.expected, trieSetup.msg) - - t.end() -}) - -tape('dummy hash', async (t) => { - const useKeyHashingFunction: HashKeysFunction = (msg) => { - const hashLen = 32 - if (msg.length <= hashLen - 5) { - return concatBytes(utf8ToBytes('hash_'), new Uint8Array(hashLen - msg.length).fill(0), msg) - } else { - return concatBytes(utf8ToBytes('hash_'), msg.slice(0, hashLen - 5)) + + tape('dummy hash', async (t) => { + const useKeyHashingFunction: HashKeysFunction = (msg) => { + const hashLen = 32 + if (msg.length <= hashLen - 5) { + return concatBytes(utf8ToBytes('hash_'), new Uint8Array(hashLen - msg.length).fill(0), msg) + } else { + return concatBytes(utf8ToBytes('hash_'), msg.slice(0, hashLen - 5)) + } } - } - const [k, v] = [utf8ToBytes('foo'), utf8ToBytes('bar')] - const expectedRoot = useKeyHashingFunction(new LeafNode(bytesToNibbles(k), v).serialize()) + const [k, v] = [utf8ToBytes('foo'), utf8ToBytes('bar')] + const expectedRoot = useKeyHashingFunction(new LeafNode(bytesToNibbles(k), v).serialize()) - const trie = new Trie({ useKeyHashingFunction }) - await trie.put(k, v) - t.equal(bytesToHex(trie.root()), bytesToHex(expectedRoot)) + const trie = new Trie({ useKeyHashingFunction, cacheSize }) + await trie.put(k, v) + t.equal(bytesToHex(trie.root()), bytesToHex(expectedRoot)) - t.end() -}) + t.end() + }) -tape('blake2b256 trie root', async (t) => { - const trie = new Trie({ useKeyHashingFunction: (msg) => blake2b(msg, 32) }) - await trie.put(utf8ToBytes('foo'), utf8ToBytes('bar')) + tape('blake2b256 trie root', async (t) => { + const trie = new Trie({ useKeyHashingFunction: (msg) => blake2b(msg, 32), cacheSize }) + await trie.put(utf8ToBytes('foo'), utf8ToBytes('bar')) - t.equal( - bytesToHex(trie.root()), - 'e118db4e01512253df38daafa16fc1d69e03e755595b5847d275d7404ebdc74a' - ) - t.end() -}) + t.equal( + bytesToHex(trie.root()), + 'e118db4e01512253df38daafa16fc1d69e03e755595b5847d275d7404ebdc74a' + ) + t.end() + }) -tape('empty root', async (t) => { - const trie = new Trie() + tape('empty root', async (t) => { + const trie = new Trie({ cacheSize }) - t.equal(bytesToHex(trie.root()), KECCAK256_RLP_S) - t.end() -}) + t.equal(bytesToHex(trie.root()), KECCAK256_RLP_S) + t.end() + }) +} From d7e8ce14219483a9ea9780049d718e3a93a1d28c Mon Sep 17 00:00:00 2001 From: acolytec3 Date: Wed, 26 Apr 2023 11:54:33 -0400 Subject: [PATCH 26/53] Use JS maps in cache (#2665) * Switch accountCache diffcache to JS Maps * Fix commit * Switch storage diffCache to array of maps * Fix storage cache prestate check --------- Co-authored-by: Holger Drewes Co-authored-by: Jochem Brouwer --- packages/statemanager/src/cache/account.ts | 45 +++----- packages/statemanager/src/cache/storage.ts | 127 +++++++++------------ 2 files changed, 74 insertions(+), 98 deletions(-) diff --git a/packages/statemanager/src/cache/account.ts b/packages/statemanager/src/cache/account.ts index f41c2da85a..01fc8f0b7a 100644 --- a/packages/statemanager/src/cache/account.ts +++ b/packages/statemanager/src/cache/account.ts @@ -33,8 +33,7 @@ export class AccountCache extends Cache { * to the account), the element didn't exist in the cache * before. */ - _diffCache: OrderedMap[] = [] - + _diffCache: Map[] = [] constructor(opts: CacheOpts) { super() if (opts.type === CacheType.LRU) { @@ -46,20 +45,20 @@ export class AccountCache extends Cache { this._orderedMapCache = new OrderedMap() } - this._diffCache.push(new OrderedMap()) + this._diffCache.push(new Map()) this._debug = createDebugLogger('statemanager:cache:account') } _saveCachePreState(cacheKeyHex: string) { - const it = this._diffCache[this._checkpoints].find(cacheKeyHex) - if (it.equals(this._diffCache[this._checkpoints].end())) { + const it = this._diffCache[this._checkpoints].get(cacheKeyHex) + if (it === undefined) { let oldElem: AccountCacheElement | undefined if (this._lruCache) { oldElem = this._lruCache!.get(cacheKeyHex) } else { oldElem = this._orderedMapCache!.getElementByKey(cacheKeyHex) } - this._diffCache[this._checkpoints].setElement(cacheKeyHex, oldElem) + this._diffCache[this._checkpoints].set(cacheKeyHex, oldElem) } } @@ -142,12 +141,11 @@ export class AccountCache extends Cache { } const diffMap = this._diffCache[this._checkpoints]! - const it = diffMap.begin() const items: [string, AccountCacheElement][] = [] - while (!it.equals(diffMap.end())) { - const cacheKeyHex = it.pointer[0] + for (const entry of diffMap.entries()) { + const cacheKeyHex = entry[0] let elem: AccountCacheElement | undefined if (this._lruCache) { elem = this._lruCache!.get(cacheKeyHex) @@ -158,9 +156,8 @@ export class AccountCache extends Cache { if (elem !== undefined) { items.push([cacheKeyHex, elem]) } - it.next() } - this._diffCache[this._checkpoints] = new OrderedMap() + this._diffCache[this._checkpoints] = new Map() return items } @@ -173,11 +170,9 @@ export class AccountCache extends Cache { this._debug(`Revert to checkpoint ${this._checkpoints}`) } const diffMap = this._diffCache.pop()! - - const it = diffMap.begin() - while (!it.equals(diffMap.end())) { - const addressHex = it.pointer[0] - const elem = it.pointer[1] + for (const entry of diffMap.entries()) { + const addressHex = entry[0] + const elem = entry[1] if (elem === undefined) { if (this._lruCache) { this._lruCache!.delete(addressHex) @@ -191,7 +186,6 @@ export class AccountCache extends Cache { this._orderedMapCache!.setElement(addressHex, elem) } } - it.next() } } @@ -204,16 +198,13 @@ export class AccountCache extends Cache { this._debug(`Commit to checkpoint ${this._checkpoints}`) } const diffMap = this._diffCache.pop()! - - const it = diffMap.begin() - while (!it.equals(diffMap.end())) { - const addressHex = it.pointer[0] - const itOld = this._diffCache[this._checkpoints].find(addressHex) - if (itOld.equals(this._diffCache[this._checkpoints].end())) { - const elem = it.pointer[1] - this._diffCache[this._checkpoints].setElement(addressHex, elem) + for (const entry of diffMap.entries()) { + const addressHex = entry[0] + const oldEntry = this._diffCache[this._checkpoints].has(addressHex) + if (!oldEntry) { + const elem = entry[1] + this._diffCache[this._checkpoints].set(addressHex, elem) } - it.next() } } @@ -226,7 +217,7 @@ export class AccountCache extends Cache { if (this.DEBUG) { this._debug(`New checkpoint ${this._checkpoints}`) } - this._diffCache.push(new OrderedMap()) + this._diffCache.push(new Map()) } /** diff --git a/packages/statemanager/src/cache/storage.ts b/packages/statemanager/src/cache/storage.ts index 57fc603385..7a3b7dc5b8 100644 --- a/packages/statemanager/src/cache/storage.ts +++ b/packages/statemanager/src/cache/storage.ts @@ -16,8 +16,8 @@ const LRU = require('lru-cache') * * undefined: storage value is known not to exist in the cache */ -type DiffStorageCacheMap = OrderedMap -type StorageCacheMap = OrderedMap +type DiffStorageCacheMap = Map +type StorageCacheMap = Map export class StorageCache extends Cache { _lruCache: LRUCache | undefined @@ -32,7 +32,7 @@ export class StorageCache extends Cache { * to the account), the element didn't exist in the cache * before. */ - _diffCache: OrderedMap[] = [] + _diffCache: Map[] = [] constructor(opts: CacheOpts) { super() @@ -45,7 +45,7 @@ export class StorageCache extends Cache { this._orderedMapCache = new OrderedMap() } - this._diffCache.push(new OrderedMap()) + this._diffCache.push(new Map()) if (this.DEBUG) { this._debug = createDebugLogger('statemanager:cache:storage') @@ -53,31 +53,30 @@ export class StorageCache extends Cache { } _saveCachePreState(addressHex: string, keyHex: string) { - const itAddress = this._diffCache[this._checkpoints].find(addressHex) + const addressStoragePreState = this._diffCache[this._checkpoints].get(addressHex) let diffStorageMap: DiffStorageCacheMap - if (itAddress.equals(this._diffCache[this._checkpoints].end())) { - diffStorageMap = new OrderedMap() + if (addressStoragePreState === undefined) { + diffStorageMap = new Map() } else { - diffStorageMap = itAddress.pointer[1] + diffStorageMap = addressStoragePreState } - const itKey = diffStorageMap.find(keyHex) - if (itKey.equals(diffStorageMap.end())) { + if (!diffStorageMap.has(keyHex)) { let oldStorageMap: StorageCacheMap | undefined let oldStorage: Uint8Array | undefined = undefined if (this._lruCache) { oldStorageMap = this._lruCache!.get(addressHex) if (oldStorageMap) { - oldStorage = oldStorageMap.getElementByKey(keyHex) + oldStorage = oldStorageMap.get(keyHex) } } else { oldStorageMap = this._orderedMapCache!.getElementByKey(addressHex) if (oldStorageMap) { - oldStorage = oldStorageMap.getElementByKey(keyHex) + oldStorage = oldStorageMap.get(keyHex) } } - diffStorageMap.setElement(keyHex, oldStorage) - this._diffCache[this._checkpoints].setElement(addressHex, diffStorageMap) + diffStorageMap.set(keyHex, oldStorage) + this._diffCache[this._checkpoints].set(addressHex, diffStorageMap) } } @@ -102,16 +101,16 @@ export class StorageCache extends Cache { if (this._lruCache) { let storageMap = this._lruCache!.get(addressHex) if (!storageMap) { - storageMap = new OrderedMap() + storageMap = new Map() } - storageMap.setElement(keyHex, value) + storageMap.set(keyHex, value) this._lruCache!.set(addressHex, storageMap) } else { let storageMap = this._orderedMapCache!.getElementByKey(addressHex) if (!storageMap) { - storageMap = new OrderedMap() + storageMap = new Map() } - storageMap.setElement(keyHex, value) + storageMap.set(keyHex, value) this._orderedMapCache!.setElement(addressHex, storageMap) } this._stats.writes += 1 @@ -141,7 +140,7 @@ export class StorageCache extends Cache { this._stats.reads += 1 if (storageMap) { this._stats.hits += 1 - return storageMap.getElementByKey(keyHex) + return storageMap.get(keyHex) } } @@ -160,16 +159,16 @@ export class StorageCache extends Cache { if (this._lruCache) { let storageMap = this._lruCache!.get(addressHex) if (!storageMap) { - storageMap = new OrderedMap() + storageMap = new Map() } - storageMap.setElement(keyHex, hexStringToBytes('80')) + storageMap.set(keyHex, hexStringToBytes('80')) this._lruCache!.set(addressHex, storageMap) } else { let storageMap = this._orderedMapCache!.getElementByKey(addressHex) if (!storageMap) { - storageMap = new OrderedMap() + storageMap = new Map() } - storageMap.setElement(keyHex, hexStringToBytes('80')) + storageMap.set(keyHex, hexStringToBytes('80')) this._orderedMapCache!.setElement(addressHex, storageMap) } @@ -183,9 +182,9 @@ export class StorageCache extends Cache { clearContractStorage(address: Address): void { const addressHex = bytesToHex(address.bytes) if (this._lruCache) { - this._lruCache!.set(addressHex, new OrderedMap()) + this._lruCache!.set(addressHex, new Map()) } else { - this._orderedMapCache!.setElement(addressHex, new OrderedMap()) + this._orderedMapCache!.setElement(addressHex, new Map()) } } @@ -199,13 +198,12 @@ export class StorageCache extends Cache { } const diffMap = this._diffCache[this._checkpoints]! - const it = diffMap.begin() const items: [string, string, Uint8Array | undefined][] = [] - while (!it.equals(diffMap.end())) { - const addressHex = it.pointer[0] - const diffStorageMap = it.pointer[1] + for (const entry of diffMap.entries()) { + const addressHex = entry[0] + const diffStorageMap = entry[1] let storageMap: StorageCacheMap | undefined if (this._lruCache) { storageMap = this._lruCache!.get(addressHex) @@ -214,19 +212,16 @@ export class StorageCache extends Cache { } if (storageMap !== undefined) { - const itDiffStorage = diffStorageMap.begin() - while (!itDiffStorage.equals(diffStorageMap.end())) { - const keyHex = itDiffStorage.pointer[0] - const value = storageMap.getElementByKey(keyHex) + for (const entry of diffStorageMap.entries()) { + const keyHex = entry[0] + const value = storageMap.get(keyHex) items.push([addressHex, keyHex, value]) - itDiffStorage.next() } } else { throw new Error('internal error: storage cache map for account should be defined') } - it.next() } - this._diffCache[this._checkpoints] = new OrderedMap() + this._diffCache[this._checkpoints] = new Map() return items } @@ -240,39 +235,35 @@ export class StorageCache extends Cache { } const diffMap = this._diffCache.pop()! - const it = diffMap.begin() - while (!it.equals(diffMap.end())) { - const addressHex = it.pointer[0] - const diffStorageMap = it.pointer[1] + for (const entry of diffMap.entries()) { + const addressHex = entry[0] + const diffStorageMap = entry[1] - const itStorage = diffStorageMap.begin() - while (!itStorage.equals(diffStorageMap.end())) { - const keyHex = itStorage.pointer[0] - const value = itStorage.pointer[1] + for (const entry of diffStorageMap.entries()) { + const keyHex = entry[0] + const value = entry[1] if (this._lruCache) { - const storageMap = this._lruCache.get(addressHex) ?? new OrderedMap() + const storageMap = this._lruCache.get(addressHex) ?? new Map() if (value === undefined) { // Value is known not to be in the cache before // -> delete from cache - storageMap.eraseElementByKey(keyHex) + storageMap.delete(keyHex) } else { // Value is known to be in the cache before // (being either some storage value or the RLP-encoded empty Uint8Array) - storageMap.setElement(keyHex, value) + storageMap.set(keyHex, value) } this._lruCache.set(addressHex, storageMap) } else { - const storageMap = this._orderedMapCache!.getElementByKey(addressHex) ?? new OrderedMap() + const storageMap = this._orderedMapCache!.getElementByKey(addressHex) ?? new Map() if (!value) { - storageMap.eraseElementByKey(keyHex) + storageMap.delete(keyHex) } else { - storageMap.setElement(keyHex, value) + storageMap.set(keyHex, value) } this._orderedMapCache!.setElement(addressHex, storageMap) } - itStorage.next() } - it.next() } } @@ -287,30 +278,24 @@ export class StorageCache extends Cache { const higherHeightDiffMap = this._diffCache.pop()! const lowerHeightDiffMap = this._diffCache[this._checkpoints] - const it = higherHeightDiffMap.begin() // Go through diffMap from the pre-commit checkpoint height. // 1. Iterate through all state pre states // 2. If state pre-state is not in the new (lower) height diff map, take pre commit pre state value // 3. If state is in new map, take this one, since this superseeds subsequent changes - while (!it.equals(higherHeightDiffMap.end())) { - const addressHex = it.pointer[0] - const higherHeightStorageDiff = it.pointer[1] - - const itHigherHeightStorageDiff = higherHeightStorageDiff.begin() - const lowerHeightStorageDiff = - lowerHeightDiffMap.getElementByKey(addressHex) ?? new OrderedMap() - - while (!itHigherHeightStorageDiff.equals(higherHeightStorageDiff.end())) { - const keyHex = itHigherHeightStorageDiff.pointer[0] - const lowerHeightIt = lowerHeightStorageDiff.find(keyHex) - if (lowerHeightIt.equals(lowerHeightStorageDiff.end())) { - const elem = itHigherHeightStorageDiff.pointer[1] - lowerHeightStorageDiff.setElement(keyHex, elem) + for (const entry of higherHeightDiffMap.entries()) { + const addressHex = entry[0] + const higherHeightStorageDiff = entry[1] + + const lowerHeightStorageDiff = lowerHeightDiffMap.get(addressHex) ?? new Map() + + for (const entry of higherHeightStorageDiff.entries()) { + const keyHex = entry[0] + if (!lowerHeightStorageDiff.has(keyHex)) { + const elem = entry[1] + lowerHeightStorageDiff.set(keyHex, elem) } - itHigherHeightStorageDiff.next() } - lowerHeightDiffMap.setElement(addressHex, lowerHeightStorageDiff) - it.next() + lowerHeightDiffMap.set(addressHex, lowerHeightStorageDiff) } } @@ -323,7 +308,7 @@ export class StorageCache extends Cache { if (this.DEBUG) { this._debug(`New checkpoint ${this._checkpoints}`) } - this._diffCache.push(new OrderedMap()) + this._diffCache.push(new Map()) } /** From c1dd061a122c17593f11b1ba098f0f7913f69244 Mon Sep 17 00:00:00 2001 From: Holger Drewes Date: Fri, 28 Apr 2023 17:22:27 +0200 Subject: [PATCH 27/53] Client short-term "Execution Mode" Mitigations (#2668) * Client: updated Yargs version, added types, switch to ESM import * Client: rename syncMode option to sync * Client: rename syncMode option to sync, allow for setting to none * Client: cautiously set maxPerRequest (sync) and numBlocksPerIteration (exec) from 50 to 100 * Test fixes * Client: earlier execution stop on client shutdown to avoid stateRoot failures * Attempted client CLI test fix * client: fix test shutting down RPC after first baseCall --------- Co-authored-by: Jochem Brouwer --- package-lock.json | 49 ++++++++++++++++--- packages/client/bin/cli.ts | 13 +++-- packages/client/lib/client.ts | 7 +-- packages/client/lib/config.ts | 7 +-- packages/client/lib/execution/execution.ts | 7 +++ packages/client/lib/execution/vmexecution.ts | 3 +- packages/client/lib/rpc/modules/eth.ts | 3 ++ .../client/lib/service/ethereumservice.ts | 10 ++-- .../client/lib/service/fullethereumservice.ts | 39 +++++++++------ packages/client/lib/types.ts | 3 +- packages/client/package.json | 3 +- packages/client/test/cli/cli-libp2p.spec.ts | 2 +- packages/client/test/cli/cli-sync.spec.ts | 2 +- .../test/integration/beaconsync.spec.ts | 8 +-- .../client/test/integration/fullsync.spec.ts | 8 +-- .../client/test/integration/lightsync.spec.ts | 8 +-- .../client/test/integration/merge.spec.ts | 4 +- .../client/test/integration/miner.spec.ts | 2 +- .../test/rpc/eth/getTransactionByHash.spec.ts | 2 +- packages/client/test/rpc/eth/syncing.spec.ts | 2 +- packages/client/test/rpc/helpers.ts | 7 ++- .../test/service/fullethereumservice.spec.ts | 6 +-- 22 files changed, 129 insertions(+), 66 deletions(-) diff --git a/package-lock.json b/package-lock.json index 4c8b86f565..f623a02f2d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3360,6 +3360,21 @@ "@types/node": "*" } }, + "node_modules/@types/yargs": { + "version": "17.0.24", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.24.tgz", + "integrity": "sha512-6i0aC7jV6QzQB8ne1joVZ0eSFIstHsCrobmOtghM11yGlH0j43FKL2UhWdELkyps0zuf7qVTUVCCR+tgSlyLLw==", + "dev": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.0", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", + "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", + "dev": true + }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "5.33.1", "dev": true, @@ -17906,7 +17921,7 @@ "qheap": "^1.4.0", "winston": "^3.3.3", "winston-daily-rotate-file": "^4.5.5", - "yargs": "^17.2.1" + "yargs": "^17.7.1" }, "bin": { "ethereumjs": "dist/bin/cli.js" @@ -17916,6 +17931,7 @@ "@types/connect": "^3.4.35", "@types/fs-extra": "^9.0.13", "@types/jwt-simple": "^0.5.33", + "@types/yargs": "^17.0.24", "constants-browserify": "^1.0.0", "crypto-browserify": "^3.12.0", "file-replace-loader": "^1.2.0", @@ -17973,8 +17989,9 @@ } }, "packages/client/node_modules/yargs": { - "version": "17.6.0", - "license": "MIT", + "version": "17.7.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.1.tgz", + "integrity": "sha512-cwiTb08Xuv5fqF4AovYacTFNxk62th7LKJ6BL9IGUpTJrWoU7/7WdQGTP2SjKf1dUNBGzDd28p/Yfs/GI6JrLw==", "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", @@ -17982,7 +17999,7 @@ "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", - "yargs-parser": "^21.0.0" + "yargs-parser": "^21.1.1" }, "engines": { "node": ">=12" @@ -19603,6 +19620,7 @@ "@types/connect": "^3.4.35", "@types/fs-extra": "^9.0.13", "@types/jwt-simple": "^0.5.33", + "@types/yargs": "^17.0.24", "abstract-level": "^1.0.3", "body-parser": "^1.19.2", "c-kzg": "^2.0.4", @@ -19645,7 +19663,7 @@ "webpack-cli": "^4.8.0", "winston": "^3.3.3", "winston-daily-rotate-file": "^4.5.5", - "yargs": "^17.2.1" + "yargs": "^17.7.1" }, "dependencies": { "cliui": { @@ -19671,7 +19689,9 @@ } }, "yargs": { - "version": "17.6.0", + "version": "17.7.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.1.tgz", + "integrity": "sha512-cwiTb08Xuv5fqF4AovYacTFNxk62th7LKJ6BL9IGUpTJrWoU7/7WdQGTP2SjKf1dUNBGzDd28p/Yfs/GI6JrLw==", "requires": { "cliui": "^8.0.1", "escalade": "^3.1.1", @@ -19679,7 +19699,7 @@ "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", - "yargs-parser": "^21.0.0" + "yargs-parser": "^21.1.1" } }, "yargs-parser": { @@ -20868,6 +20888,21 @@ "@types/node": "*" } }, + "@types/yargs": { + "version": "17.0.24", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.24.tgz", + "integrity": "sha512-6i0aC7jV6QzQB8ne1joVZ0eSFIstHsCrobmOtghM11yGlH0j43FKL2UhWdELkyps0zuf7qVTUVCCR+tgSlyLLw==", + "dev": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "@types/yargs-parser": { + "version": "21.0.0", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", + "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", + "dev": true + }, "@typescript-eslint/eslint-plugin": { "version": "5.33.1", "dev": true, diff --git a/packages/client/bin/cli.ts b/packages/client/bin/cli.ts index e1e24e43dd..b454db5e91 100755 --- a/packages/client/bin/cli.ts +++ b/packages/client/bin/cli.ts @@ -21,6 +21,8 @@ import { Level } from 'level' import { homedir } from 'os' import * as path from 'path' import * as readline from 'readline' +import yargs from 'yargs' +import { hideBin } from 'yargs/helpers' import { EthereumClient } from '../lib/client' import { Config, DataDirectory, SyncMode } from '../lib/config' @@ -38,16 +40,17 @@ import type { BlockBytes } from '@ethereumjs/block' import type { GenesisState } from '@ethereumjs/blockchain/dist/genesisStates' import type { AbstractLevel } from 'abstract-level' -const { hideBin } = require('yargs/helpers') -const yargs = require('yargs/yargs') - type Account = [address: Address, privateKey: Uint8Array] const networks = Object.entries(Common._getInitializedChains().names) let logger: Logger +// @ts-ignore const args: ClientOpts = yargs(hideBin(process.argv)) + .parserConfiguration({ + 'dot-notation': false, + }) .option('network', { describe: 'Network', choices: networks.map((n) => n[1]), @@ -58,7 +61,7 @@ const args: ClientOpts = yargs(hideBin(process.argv)) choices: networks.map((n) => parseInt(n[0])), default: undefined, }) - .option('syncMode', { + .option('sync', { describe: 'Blockchain sync mode (light sync experimental)', choices: Object.values(SyncMode), default: Config.SYNCMODE_DEFAULT, @@ -754,7 +757,7 @@ async function run() { multiaddrs, port: args.port, saveReceipts: args.saveReceipts, - syncmode: args.syncMode, + syncmode: args.sync, disableBeaconSync: args.disableBeaconSync, forceSnapSync: args.forceSnapSync, transports: args.transports, diff --git a/packages/client/lib/client.ts b/packages/client/lib/client.ts index 817da52231..65fd52617a 100644 --- a/packages/client/lib/client.ts +++ b/packages/client/lib/client.ts @@ -59,7 +59,7 @@ export interface EthereumClientOptions { export class EthereumClient { public config: Config public chain: Chain - public services: (FullEthereumService | LightEthereumService)[] + public services: (FullEthereumService | LightEthereumService)[] = [] public opened: boolean public started: boolean @@ -82,7 +82,7 @@ export class EthereumClient { this.config = options.config this.chain = chain - if (this.config.syncmode === SyncMode.Full) { + if (this.config.syncmode === SyncMode.Full || this.config.syncmode === SyncMode.None) { this.services = [ new FullEthereumService({ config: this.config, @@ -92,7 +92,8 @@ export class EthereumClient { chain, }), ] - } else { + } + if (this.config.syncmode === SyncMode.Light) { this.services = [ new LightEthereumService({ config: this.config, diff --git a/packages/client/lib/config.ts b/packages/client/lib/config.ts index da21081bda..ecd98534c1 100644 --- a/packages/client/lib/config.ts +++ b/packages/client/lib/config.ts @@ -23,6 +23,7 @@ export enum DataDirectory { export enum SyncMode { Full = 'full', Light = 'light', + None = 'none', } export interface ConfigOptions { @@ -146,7 +147,7 @@ export interface ConfigOptions { /** * Max items per block or header request * - * Default: `50`` + * Default: `100` */ maxPerRequest?: number @@ -303,13 +304,13 @@ export class Config { public static readonly DATADIR_DEFAULT = `./datadir` public static readonly TRANSPORTS_DEFAULT = ['rlpx'] public static readonly PORT_DEFAULT = 30303 - public static readonly MAXPERREQUEST_DEFAULT = 50 + public static readonly MAXPERREQUEST_DEFAULT = 100 public static readonly MAXFETCHERJOBS_DEFAULT = 100 public static readonly MAXFETCHERREQUESTS_DEFAULT = 5 public static readonly MINPEERS_DEFAULT = 1 public static readonly MAXPEERS_DEFAULT = 25 public static readonly DNSADDR_DEFAULT = '8.8.8.8' - public static readonly NUM_BLOCKS_PER_ITERATION = 50 + public static readonly NUM_BLOCKS_PER_ITERATION = 100 public static readonly ACCOUNT_CACHE = 1000000 public static readonly STORAGE_CACHE = 200000 public static readonly TRIE_CACHE = 500000 diff --git a/packages/client/lib/execution/execution.ts b/packages/client/lib/execution/execution.ts index c0c43c1ddd..0fe0c264b3 100644 --- a/packages/client/lib/execution/execution.ts +++ b/packages/client/lib/execution/execution.ts @@ -1,3 +1,5 @@ +import { Event } from '../types' + import type { Chain } from '../blockchain' import type { Config } from '../config' import type { AbstractLevel } from 'abstract-level' @@ -25,6 +27,7 @@ export abstract class Execution { public running: boolean = false public started: boolean = false + public shutdown: boolean = false /** * Create new execution module @@ -35,6 +38,10 @@ export abstract class Execution { this.chain = options.chain this.stateDB = options.stateDB this.metaDB = options.metaDB + + this.config.events.once(Event.CLIENT_SHUTDOWN, () => { + this.shutdown = true + }) } /** diff --git a/packages/client/lib/execution/vmexecution.ts b/packages/client/lib/execution/vmexecution.ts index 297c13b766..8211862411 100644 --- a/packages/client/lib/execution/vmexecution.ts +++ b/packages/client/lib/execution/vmexecution.ts @@ -257,7 +257,7 @@ export class VMExecution extends Execution { * @returns number of blocks executed */ async run(loop = true, runOnlybatched = false): Promise { - if (this.running || !this.started) return 0 + if (this.running || !this.started || this.shutdown) return 0 this.running = true let numExecuted: number | undefined @@ -281,6 +281,7 @@ export class VMExecution extends Execution { while ( this.started && + !this.shutdown && (!runOnlybatched || (runOnlybatched && canonicalHead.header.number - startHeadBlock.header.number >= diff --git a/packages/client/lib/rpc/modules/eth.ts b/packages/client/lib/rpc/modules/eth.ts index 490ce4a773..5909c07f62 100644 --- a/packages/client/lib/rpc/modules/eth.ts +++ b/packages/client/lib/rpc/modules/eth.ts @@ -1028,6 +1028,9 @@ export class Eth { const currentBlock = bigIntToHex(currentBlockHeader.number) const synchronizer = this.client.services[0].synchronizer + if (!synchronizer) { + return false + } const { syncTargetHeight } = this.client.config const startingBlock = bigIntToHex(synchronizer.startingBlock) diff --git a/packages/client/lib/service/ethereumservice.ts b/packages/client/lib/service/ethereumservice.ts index f783156441..0bac4c841b 100644 --- a/packages/client/lib/service/ethereumservice.ts +++ b/packages/client/lib/service/ethereumservice.ts @@ -36,7 +36,7 @@ export class EthereumService extends Service { public chain: Chain public interval: number public timeout: number - public synchronizer!: Synchronizer + public synchronizer?: Synchronizer /** * Create new ETH service @@ -67,7 +67,7 @@ export class EthereumService extends Service { } await super.open() await this.chain.open() - await this.synchronizer.open() + await this.synchronizer?.open() return true } @@ -79,7 +79,7 @@ export class EthereumService extends Service { return false } await super.start() - void this.synchronizer.start() + void this.synchronizer?.start() return true } @@ -90,7 +90,7 @@ export class EthereumService extends Service { if (!this.running) { return false } - await this.synchronizer.stop() + await this.synchronizer?.stop() await super.stop() return true } @@ -100,7 +100,7 @@ export class EthereumService extends Service { */ async close() { if (this.opened) { - await this.synchronizer.close() + await this.synchronizer?.close() } await super.close() } diff --git a/packages/client/lib/service/fullethereumservice.ts b/packages/client/lib/service/fullethereumservice.ts index 3c76f8c50c..a8ea53d227 100644 --- a/packages/client/lib/service/fullethereumservice.ts +++ b/packages/client/lib/service/fullethereumservice.ts @@ -2,6 +2,7 @@ import { Hardfork } from '@ethereumjs/common' import { encodeReceipt } from '@ethereumjs/vm/dist/runBlock' import { concatBytes } from 'ethereum-cryptography/utils' +import { SyncMode } from '../config' import { VMExecution } from '../execution' import { Miner } from '../miner' import { EthProtocol } from '../net/protocol/ethprotocol' @@ -28,7 +29,7 @@ interface FullEthereumServiceOptions extends EthereumServiceOptions { * @memberof module:service */ export class FullEthereumService extends EthereumService { - public synchronizer!: BeaconSynchronizer | FullSynchronizer | SnapSynchronizer + public synchronizer?: BeaconSynchronizer | FullSynchronizer | SnapSynchronizer public lightserv: boolean public miner: Miner | undefined public execution: VMExecution @@ -73,14 +74,16 @@ export class FullEthereumService extends EthereumService { } this.config.logger.info(`Post-merge 🐼 client mode: run with CL client.`) } else { - this.synchronizer = new FullSynchronizer({ - config: this.config, - pool: this.pool, - chain: this.chain, - txPool: this.txPool, - execution: this.execution, - interval: this.interval, - }) + if (this.config.syncmode === SyncMode.Full) { + this.synchronizer = new FullSynchronizer({ + config: this.config, + pool: this.pool, + chain: this.chain, + txPool: this.txPool, + execution: this.execution, + interval: this.interval, + }) + } } } @@ -129,11 +132,17 @@ export class FullEthereumService extends EthereumService { } async open() { - this.config.logger.info( - `Preparing for sync using FullEthereumService with ${ - this.synchronizer instanceof BeaconSynchronizer ? 'BeaconSynchronizer' : 'FullSynchronizer' - }.` - ) + if (this.synchronizer !== undefined) { + this.config.logger.info( + `Preparing for sync using FullEthereumService with ${ + this.synchronizer instanceof BeaconSynchronizer + ? 'BeaconSynchronizer' + : 'FullSynchronizer' + }.` + ) + } else { + this.config.logger.info('Starting FullEthereumService with no syncing.') + } await super.open() await this.execution.open() this.txPool.open() @@ -168,7 +177,7 @@ export class FullEthereumService extends EthereumService { } this.txPool.stop() this.miner?.stop() - await this.synchronizer.stop() + await this.synchronizer?.stop() await this.execution.stop() await super.stop() return true diff --git a/packages/client/lib/types.ts b/packages/client/lib/types.ts index b2be86c8cf..6c32062fb1 100644 --- a/packages/client/lib/types.ts +++ b/packages/client/lib/types.ts @@ -105,7 +105,7 @@ export type Libp2pMuxedStream = MuxedStream export interface ClientOpts { network?: string networkId?: number - syncMode?: SyncMode + sync?: SyncMode lightServe?: boolean dataDir?: string customChain?: string @@ -162,6 +162,5 @@ export interface ClientOpts { txLookupLimit?: number startBlock?: number isSingleNode?: boolean - opened: boolean loadBlocksFromRlp?: string } diff --git a/packages/client/package.json b/packages/client/package.json index 6de352750b..21d848c671 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -94,13 +94,14 @@ "qheap": "^1.4.0", "winston": "^3.3.3", "winston-daily-rotate-file": "^4.5.5", - "yargs": "^17.2.1" + "yargs": "^17.7.1" }, "devDependencies": { "@types/body-parser": "^1.19.2", "@types/connect": "^3.4.35", "@types/fs-extra": "^9.0.13", "@types/jwt-simple": "^0.5.33", + "@types/yargs": "^17.0.24", "constants-browserify": "^1.0.0", "crypto-browserify": "^3.12.0", "file-replace-loader": "^1.2.0", diff --git a/packages/client/test/cli/cli-libp2p.spec.ts b/packages/client/test/cli/cli-libp2p.spec.ts index de6a5ec060..a7e0f2d2f2 100644 --- a/packages/client/test/cli/cli-libp2p.spec.ts +++ b/packages/client/test/cli/cli-libp2p.spec.ts @@ -47,7 +47,7 @@ tape('[CLI] rpc', (t) => { '--mine=false', '--dev', '--multiaddrs=/ip4/0.0.0.0/tcp/50506', - '--syncMode=light', + '--sync=light', '--logLevel=debug', ], ]) diff --git a/packages/client/test/cli/cli-sync.spec.ts b/packages/client/test/cli/cli-sync.spec.ts index aa3ebbf47b..31ee0ae0db 100644 --- a/packages/client/test/cli/cli-sync.spec.ts +++ b/packages/client/test/cli/cli-sync.spec.ts @@ -3,7 +3,7 @@ import * as tape from 'tape' // get args for --network and --syncmode const cliArgs = process.argv.filter( - (arg) => arg.startsWith('--network') || arg.startsWith('--syncMode') + (arg) => arg.startsWith('--network') || arg.startsWith('--sync') ) tape('[CLI] sync', (t) => { diff --git a/packages/client/test/integration/beaconsync.spec.ts b/packages/client/test/integration/beaconsync.spec.ts index 62b1faa75d..62d46f0d3d 100644 --- a/packages/client/test/integration/beaconsync.spec.ts +++ b/packages/client/test/integration/beaconsync.spec.ts @@ -28,14 +28,14 @@ tape('[Integration:BeaconSync]', async (t) => { next: next.hash(), }, ] - await localService.synchronizer.stop() + await localService.synchronizer!.stop() await localServer.discover('remotePeer1', '127.0.0.2') localService.config.events.on(Event.SYNC_SYNCHRONIZED, async () => { t.equals(localService.chain.blocks.height, BigInt(20), 'synced') await destroy(localServer, localService) await destroy(remoteServer, remoteService) }) - await localService.synchronizer.start() + await localService.synchronizer!.start() }) t.test('should not sync with stale peers', async (t) => { @@ -76,7 +76,7 @@ tape('[Integration:BeaconSync]', async (t) => { }, ] localService.interval = 1000 - await localService.synchronizer.stop() + await localService.synchronizer!.stop() await localServer.discover('remotePeer1', '127.0.0.2') await localServer.discover('remotePeer2', '127.0.0.3') @@ -88,7 +88,7 @@ tape('[Integration:BeaconSync]', async (t) => { await destroy(remoteServer2, remoteService2) } }) - await localService.synchronizer.start() + await localService.synchronizer!.start() }) }) diff --git a/packages/client/test/integration/fullsync.spec.ts b/packages/client/test/integration/fullsync.spec.ts index 5cf53b5c19..68a9725bfe 100644 --- a/packages/client/test/integration/fullsync.spec.ts +++ b/packages/client/test/integration/fullsync.spec.ts @@ -8,7 +8,7 @@ tape('[Integration:FullSync]', async (t) => { t.test('should sync blocks', async (t) => { const [remoteServer, remoteService] = await setup({ location: '127.0.0.2', height: 20 }) const [localServer, localService] = await setup({ location: '127.0.0.1', height: 0 }) - await localService.synchronizer.stop() + await localService.synchronizer!.stop() await localServer.discover('remotePeer1', '127.0.0.2') // await localService.synchronizer.sync() localService.config.events.on(Event.SYNC_SYNCHRONIZED, async () => { @@ -16,7 +16,7 @@ tape('[Integration:FullSync]', async (t) => { await destroy(localServer, localService) await destroy(remoteServer, remoteService) }) - await localService.synchronizer.start() + await localService.synchronizer!.start() }) t.test('should not sync with stale peers', async (t) => { @@ -40,7 +40,7 @@ tape('[Integration:FullSync]', async (t) => { height: 0, minPeers: 2, }) - await localService.synchronizer.stop() + await localService.synchronizer!.stop() await localServer.discover('remotePeer1', '127.0.0.2') await localServer.discover('remotePeer2', '127.0.0.3') @@ -52,6 +52,6 @@ tape('[Integration:FullSync]', async (t) => { await destroy(remoteServer2, remoteService2) } }) - await localService.synchronizer.start() + await localService.synchronizer!.start() }) }) diff --git a/packages/client/test/integration/lightsync.spec.ts b/packages/client/test/integration/lightsync.spec.ts index 34b1f0aac4..c79e830d94 100644 --- a/packages/client/test/integration/lightsync.spec.ts +++ b/packages/client/test/integration/lightsync.spec.ts @@ -17,14 +17,14 @@ tape('[Integration:LightSync]', async (t) => { height: 0, syncmode: SyncMode.Light, }) - await localService.synchronizer.stop() + await localService.synchronizer!.stop() await localServer.discover('remotePeer1', '127.0.0.2') localService.config.events.on(Event.SYNC_SYNCHRONIZED, async () => { t.equals(localService.chain.headers.height, BigInt(20), 'synced') await destroy(localServer, localService) await destroy(remoteServer, remoteService) }) - await localService.synchronizer.start() + await localService.synchronizer!.start() }) t.test('should not sync with stale peers', async (t) => { @@ -64,7 +64,7 @@ tape('[Integration:LightSync]', async (t) => { height: 0, syncmode: SyncMode.Light, }) - await localService.synchronizer.stop() + await localService.synchronizer!.stop() await localServer.discover('remotePeer1', '127.0.0.2') await localServer.discover('remotePeer2', '127.0.0.3') localService.config.events.on(Event.SYNC_SYNCHRONIZED, async () => { @@ -75,6 +75,6 @@ tape('[Integration:LightSync]', async (t) => { await destroy(remoteServer2, remoteService2) } }) - await localService.synchronizer.start() + await localService.synchronizer!.start() }) }) diff --git a/packages/client/test/integration/merge.spec.ts b/packages/client/test/integration/merge.spec.ts index c808d2055a..c6c8839a2f 100644 --- a/packages/client/test/integration/merge.spec.ts +++ b/packages/client/test/integration/merge.spec.ts @@ -130,7 +130,7 @@ tape('[Integration:Merge]', async (t) => { t.fail('chain should not exceed merge TTD') } }) - await remoteService.synchronizer.start() + await remoteService.synchronizer!.start() await new Promise(() => {}) // resolves once t.end() is called }) @@ -169,7 +169,7 @@ tape('[Integration:Merge]', async (t) => { t.fail('chain should not exceed merge terminal block') } }) - await remoteService.synchronizer.start() + await remoteService.synchronizer!.start() await new Promise(() => {}) // resolves once t.end() is called }) }) diff --git a/packages/client/test/integration/miner.spec.ts b/packages/client/test/integration/miner.spec.ts index dc6776e975..53cfc12e53 100644 --- a/packages/client/test/integration/miner.spec.ts +++ b/packages/client/test/integration/miner.spec.ts @@ -102,7 +102,7 @@ tape('[Integration:Miner]', async (t) => { t.end() } }) - await remoteService.synchronizer.start() + await remoteService.synchronizer!.start() await new Promise(() => {}) // resolves once t.end() is called } ) diff --git a/packages/client/test/rpc/eth/getTransactionByHash.spec.ts b/packages/client/test/rpc/eth/getTransactionByHash.spec.ts index cea1aedfae..9ff9f9f98a 100644 --- a/packages/client/test/rpc/eth/getTransactionByHash.spec.ts +++ b/packages/client/test/rpc/eth/getTransactionByHash.spec.ts @@ -32,7 +32,7 @@ tape(`${method}: call with legacy tx`, async (t) => { const msg = 'should return the correct tx' t.equal(res.body.result.hash, bytesToPrefixedHexString(tx.hash()), msg) } - await baseRequest(t, server, req, 200, expectRes, false) + await baseRequest(t, server, req, 200, expectRes, false, false) // run a block to ensure tx hash index is cleaned up when txLookupLimit=1 await runBlockWithTxs(chain, execution, []) diff --git a/packages/client/test/rpc/eth/syncing.spec.ts b/packages/client/test/rpc/eth/syncing.spec.ts index 0816ae5fbd..d67e46a249 100644 --- a/packages/client/test/rpc/eth/syncing.spec.ts +++ b/packages/client/test/rpc/eth/syncing.spec.ts @@ -46,7 +46,7 @@ tape(`${method}: should return highest block header unavailable error`, async (t const manager = createManager(client) const rpcServer = startRPC(manager.getMethods()) - const synchronizer = client.services[0].synchronizer + const synchronizer = client.services[0].synchronizer! synchronizer.best = td.func() td.when(synchronizer.best()).thenResolve('peer') diff --git a/packages/client/test/rpc/helpers.ts b/packages/client/test/rpc/helpers.ts index 75428d6d17..b97a58ffe4 100644 --- a/packages/client/test/rpc/helpers.ts +++ b/packages/client/test/rpc/helpers.ts @@ -193,7 +193,8 @@ export async function baseRequest( req: Object, expect: number, expectRes: Function, - endOnFinish = true + endOnFinish = true, + doCloseRPCOnSuccess = true ) { try { await request(server) @@ -202,7 +203,9 @@ export async function baseRequest( .send(req) .expect(expect) .expect(expectRes) - closeRPC(server) + if (doCloseRPCOnSuccess) { + closeRPC(server) + } if (endOnFinish) { t.end() } diff --git a/packages/client/test/service/fullethereumservice.spec.ts b/packages/client/test/service/fullethereumservice.spec.ts index 770d679c52..53201fe2db 100644 --- a/packages/client/test/service/fullethereumservice.spec.ts +++ b/packages/client/test/service/fullethereumservice.spec.ts @@ -100,7 +100,7 @@ tape('[FullEthereumService]', async (t) => { const chain = await Chain.create({ config }) const service = new FullEthereumService({ config, chain }) await service.open() - td.verify(service.synchronizer.open()) + td.verify(service.synchronizer!.open()) td.verify(server.addProtocols(td.matchers.anything())) service.config.events.on(Event.SYNC_SYNCHRONIZED, () => t.pass('synchronized')) service.config.events.on(Event.SYNC_ERROR, (err) => { @@ -122,10 +122,10 @@ tape('[FullEthereumService]', async (t) => { const service = new FullEthereumService({ config, chain }) await service.start() - td.verify(service.synchronizer.start()) + td.verify(service.synchronizer!.start()) t.notOk(await service.start(), 'already started') await service.stop() - td.verify(service.synchronizer.stop()) + td.verify(service.synchronizer!.stop()) t.notOk(await service.stop(), 'already stopped') t.end() }) From 5520e31baf3f110f529ad7a475d5cf5f091225b9 Mon Sep 17 00:00:00 2001 From: acolytec3 Date: Mon, 1 May 2023 07:51:45 -0400 Subject: [PATCH 28/53] Migrate `fromEthersProvider` to `fromJsonRpcProvider` constructors (#2663) * Remove micro-ftch * remove unused ethers dependencies * Rename fromEthersProvider to fromJsonRpcProvider * fix statemanager tests * Fix util test * Fix statemanager test * fix td.replace typing * address feedback * Update packages/block/src/block.ts Co-authored-by: g11tech * util: fix test --------- Co-authored-by: g11tech Co-authored-by: Jochem Brouwer --- package-lock.json | 55 ++++++------ packages/block/README.md | 2 +- packages/block/package.json | 6 +- packages/block/src/block.ts | 48 ++++++---- packages/block/test/from-rpc.spec.ts | 36 ++++++-- packages/block/test/mockProvider.ts | 19 ---- .../client/test/net/peer/libp2pnode.spec.ts | 2 +- .../client/test/net/peer/libp2ppeer.spec.ts | 4 +- packages/client/test/net/peerpool.spec.ts | 2 +- .../test/net/server/libp2pserver.spec.ts | 2 +- packages/devp2p/test/dns.spec.ts | 2 +- packages/evm/package.json | 2 - .../test/ethersStateManager.spec.ts | 11 +-- packages/tx/README.md | 2 +- packages/tx/package.json | 6 +- packages/tx/src/transactionFactory.ts | 20 +++-- packages/tx/test/fromRpc.spec.ts | 39 ++++++-- packages/tx/test/mockProvider.ts | 19 ---- packages/util/src/index.ts | 1 + packages/util/src/provider.ts | 90 +++++++++++++++++++ packages/util/test/provider.spec.ts | 43 +++++++++ 21 files changed, 291 insertions(+), 120 deletions(-) delete mode 100644 packages/block/test/mockProvider.ts delete mode 100644 packages/tx/test/mockProvider.ts create mode 100644 packages/util/src/provider.ts create mode 100644 packages/util/test/provider.spec.ts diff --git a/package-lock.json b/package-lock.json index f623a02f2d..2066aea123 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14204,16 +14204,16 @@ "license": "MIT" }, "node_modules/quibble": { - "version": "0.6.14", + "version": "0.6.17", + "resolved": "https://registry.npmjs.org/quibble/-/quibble-0.6.17.tgz", + "integrity": "sha512-uybGnGrx1hAhBCmzmVny+ycKaS5F71+q+iWVzbf8x/HyeEMDGeiQFVjWl1zhi4rwfTHa05+/NIExC4L5YRNPjQ==", "dev": true, - "license": "MIT", "dependencies": { "lodash": "^4.17.21", - "resolve": "^1.20.0" + "resolve": "^1.22.1" }, "engines": { - "iojs": ">= 1.0.0", - "node": ">= 0.12.0" + "node": ">= 0.14.0" } }, "node_modules/quick-format-unescaped": { @@ -16535,17 +16535,18 @@ } }, "node_modules/testdouble": { - "version": "3.16.6", + "version": "3.17.2", + "resolved": "https://registry.npmjs.org/testdouble/-/testdouble-3.17.2.tgz", + "integrity": "sha512-oRrk1DJISNoFr3aaczIqrrhkOUQ26BsXN3SopYT/U0GTvk9hlKPCEbd9R2uxkcufKZgEfo9D1JAB4CJrjHE9cw==", "dev": true, - "license": "MIT", "dependencies": { - "lodash": "^4.17.15", - "quibble": "^0.6.7", + "lodash": "^4.17.21", + "quibble": "^0.6.17", "stringify-object-es5": "^2.5.0", "theredoc": "^1.0.0" }, "engines": { - "node": ">= 4.0.0" + "node": ">= 14" } }, "node_modules/testdouble-timers": { @@ -17837,12 +17838,12 @@ "@ethereumjs/trie": "^5.0.4", "@ethereumjs/tx": "^4.1.1", "@ethereumjs/util": "^8.0.5", - "ethereum-cryptography": "^1.1.2", - "ethers": "^5.7.1" + "ethereum-cryptography": "^1.1.2" }, "devDependencies": { "@types/lru-cache": "^5.1.0", - "c-kzg": "^2.0.4" + "c-kzg": "^2.0.4", + "testdouble": "^3.17.2" }, "engines": { "node": ">=14" @@ -18138,7 +18139,6 @@ "dependencies": { "@ethereumjs/common": "^3.1.1", "@ethereumjs/util": "^8.0.5", - "@ethersproject/providers": "^5.7.1", "debug": "^4.3.3", "ethereum-cryptography": "^1.1.2", "mcl-wasm": "^0.7.1", @@ -18146,7 +18146,6 @@ }, "devDependencies": { "@ethereumjs/statemanager": "^1.0.4", - "@ethersproject/abi": "^5.0.12", "@types/benchmark": "^1.0.33", "@types/core-js": "^2.5.0", "@types/lru-cache": "^5.1.0", @@ -18267,14 +18266,14 @@ "@ethereumjs/common": "^3.1.1", "@ethereumjs/rlp": "^4.0.1", "@ethereumjs/util": "^8.0.5", - "@ethersproject/providers": "^5.7.2", "ethereum-cryptography": "^1.1.2" }, "devDependencies": { "@types/minimist": "^1.2.0", "@types/node-dir": "^0.0.34", "minimist": "^1.2.0", - "node-dir": "^0.1.16" + "node-dir": "^0.1.16", + "testdouble": "^3.17.2" }, "engines": { "node": ">=14" @@ -19576,7 +19575,7 @@ "@types/lru-cache": "^5.1.0", "c-kzg": "^2.0.4", "ethereum-cryptography": "^1.1.2", - "ethers": "^5.7.1" + "testdouble": "^3.17.2" } }, "@ethereumjs/blockchain": { @@ -19800,8 +19799,6 @@ "@ethereumjs/common": "^3.1.1", "@ethereumjs/statemanager": "^1.0.4", "@ethereumjs/util": "^8.0.5", - "@ethersproject/abi": "^5.0.12", - "@ethersproject/providers": "^5.7.1", "@types/benchmark": "^1.0.33", "@types/core-js": "^2.5.0", "@types/lru-cache": "^5.1.0", @@ -19897,12 +19894,12 @@ "@ethereumjs/common": "^3.1.1", "@ethereumjs/rlp": "^4.0.1", "@ethereumjs/util": "^8.0.5", - "@ethersproject/providers": "^5.7.2", "@types/minimist": "^1.2.0", "@types/node-dir": "^0.0.34", "ethereum-cryptography": "^1.1.2", "minimist": "^1.2.0", - "node-dir": "^0.1.16" + "node-dir": "^0.1.16", + "testdouble": "^3.17.2" } }, "@ethereumjs/util": { @@ -28312,11 +28309,13 @@ "dev": true }, "quibble": { - "version": "0.6.14", + "version": "0.6.17", + "resolved": "https://registry.npmjs.org/quibble/-/quibble-0.6.17.tgz", + "integrity": "sha512-uybGnGrx1hAhBCmzmVny+ycKaS5F71+q+iWVzbf8x/HyeEMDGeiQFVjWl1zhi4rwfTHa05+/NIExC4L5YRNPjQ==", "dev": true, "requires": { "lodash": "^4.17.21", - "resolve": "^1.20.0" + "resolve": "^1.22.1" } }, "quick-format-unescaped": { @@ -29893,11 +29892,13 @@ } }, "testdouble": { - "version": "3.16.6", + "version": "3.17.2", + "resolved": "https://registry.npmjs.org/testdouble/-/testdouble-3.17.2.tgz", + "integrity": "sha512-oRrk1DJISNoFr3aaczIqrrhkOUQ26BsXN3SopYT/U0GTvk9hlKPCEbd9R2uxkcufKZgEfo9D1JAB4CJrjHE9cw==", "dev": true, "requires": { - "lodash": "^4.17.15", - "quibble": "^0.6.7", + "lodash": "^4.17.21", + "quibble": "^0.6.17", "stringify-object-es5": "^2.5.0", "theredoc": "^1.0.0" } diff --git a/packages/block/README.md b/packages/block/README.md index aaf8f4fa6f..b5e21c9244 100644 --- a/packages/block/README.md +++ b/packages/block/README.md @@ -31,7 +31,7 @@ There are five static factories to instantiate a `Block`: - `Block.fromRLPSerializedBlock(serialized: Buffer, opts?: BlockOptions)` - `Block.fromValuesArray(values: BlockBuffer, opts?: BlockOptions)` - `Block.fromRPC(blockData: JsonRpcBlock, uncles?: any[], opts?: BlockOptions)` -- `Block.fromEthersProvider(provider: ethers.providers.JsonRpcProvider | string, blockTag: string | bigint, opts: BlockOptions)` +- `Block.fromJsonRpcProvider(provider: string | EthersProvider, blockTag: string | bigint, opts: BlockOptions)` For `BlockHeader` instantiation analog factory methods exists, see API docs linked below. diff --git a/packages/block/package.json b/packages/block/package.json index cca736dd58..fbd77226a8 100644 --- a/packages/block/package.json +++ b/packages/block/package.json @@ -43,12 +43,12 @@ "@ethereumjs/trie": "^5.0.4", "@ethereumjs/tx": "^4.1.1", "@ethereumjs/util": "^8.0.5", - "ethereum-cryptography": "^1.1.2", - "ethers": "^5.7.1" + "ethereum-cryptography": "^1.1.2" }, "devDependencies": { "@types/lru-cache": "^5.1.0", - "c-kzg": "^2.0.4" + "c-kzg": "^2.0.4", + "testdouble": "^3.17.2" }, "engines": { "node": ">=14" diff --git a/packages/block/src/block.ts b/packages/block/src/block.ts index ee1cf6f093..3702525ee5 100644 --- a/packages/block/src/block.ts +++ b/packages/block/src/block.ts @@ -8,12 +8,13 @@ import { bigIntToHex, bytesToHex, equalsBytes, + fetchFromProvider, + getProvider, intToHex, isHexPrefixed, ssz, } from '@ethereumjs/util' import { keccak256 } from 'ethereum-cryptography/keccak' -import { ethers } from 'ethers' import { blockFromRpc } from './from-rpc' import { BlockHeader } from './header' @@ -27,7 +28,7 @@ import type { TxOptions, TypedTransaction, } from '@ethereumjs/tx' -import type { WithdrawalBytes } from '@ethereumjs/util' +import type { EthersProvider, WithdrawalBytes } from '@ethereumjs/util' /** * An object that represents the block. @@ -223,44 +224,59 @@ export class Block { } /** - * Method to retrieve a block from the provider and format as a {@link Block} - * @param provider an Ethers JsonRPCProvider + * Method to retrieve a block from a JSON-RPC provider and format as a {@link Block} + * @param provider either a url for a remote provider or an Ethers JsonRpcProvider object * @param blockTag block hash or block number to be run * @param opts {@link BlockOptions} * @returns the block specified by `blockTag` */ - public static fromEthersProvider = async ( - provider: ethers.providers.JsonRpcProvider | string, + public static fromJsonRpcProvider = async ( + provider: string | EthersProvider, blockTag: string | bigint, opts: BlockOptions ) => { let blockData - const prov = - typeof provider === 'string' ? new ethers.providers.JsonRpcProvider(provider) : provider + const providerUrl = getProvider(provider) + if (typeof blockTag === 'string' && blockTag.length === 66) { - blockData = await prov.send('eth_getBlockByHash', [blockTag, true]) + blockData = await fetchFromProvider(providerUrl, { + method: 'eth_getBlockByHash', + params: [blockTag, true], + }) } else if (typeof blockTag === 'bigint') { - blockData = await prov.send('eth_getBlockByNumber', [bigIntToHex(blockTag), true]) + blockData = await fetchFromProvider(providerUrl, { + method: 'eth_getBlockByNumber', + params: [bigIntToHex(blockTag), true], + }) } else if ( isHexPrefixed(blockTag) || blockTag === 'latest' || blockTag === 'earliest' || - blockTag === 'pending' + blockTag === 'pending' || + blockTag === 'finalized' || + blockTag === 'safe' ) { - blockData = await prov.send('eth_getBlockByNumber', [blockTag, true]) + blockData = await fetchFromProvider(providerUrl, { + method: 'eth_getBlockByNumber', + params: [blockTag, true], + }) } else { throw new Error( `expected blockTag to be block hash, bigint, hex prefixed string, or earliest/latest/pending; got ${blockTag}` ) } + if (blockData === null) { + throw new Error('No block data returned from provider') + } + const uncleHeaders = [] if (blockData.uncles.length > 0) { for (let x = 0; x < blockData.uncles.length; x++) { - const headerData = await prov.send('eth_getUncleByBlockHashAndIndex', [ - blockData.hash, - intToHex(x), - ]) + const headerData = await fetchFromProvider(providerUrl, { + method: 'eth_getUncleByBlockHashAndIndex', + params: [blockData.hash, intToHex(x)], + }) uncleHeaders.push(headerData) } } diff --git a/packages/block/test/from-rpc.spec.ts b/packages/block/test/from-rpc.spec.ts index e5d17cbde8..7ddea2f631 100644 --- a/packages/block/test/from-rpc.spec.ts +++ b/packages/block/test/from-rpc.spec.ts @@ -1,13 +1,13 @@ import { Chain, Common, Hardfork } from '@ethereumjs/common' -import { bytesToPrefixedHexString, hexStringToBytes } from '@ethereumjs/util' +import { bytesToPrefixedHexString, hexStringToBytes, randomBytes } from '@ethereumjs/util' import { bytesToHex, equalsBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' +import * as td from 'testdouble' import { blockFromRpc } from '../src/from-rpc' import { blockHeaderFromRpc } from '../src/header-from-rpc' import { Block } from '../src/index' -import { MockProvider } from './mockProvider' import * as alchemy14151203 from './testdata/alchemy14151203.json' import * as infura15571241woTxs from './testdata/infura15571241.json' import * as infura15571241wTxs from './testdata/infura15571241wtxns.json' @@ -185,15 +185,41 @@ tape('[fromRPC] - Alchemy/Infura API block responses', (t) => { t.end() }) -tape('[fromEthersProvider]', async (t) => { +tape('[fromJsonRpcProvider]', async (t) => { const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.London }) - const provider = new MockProvider() + const provider = 'https://my.json.rpc.provider.com:8545' + + const fakeFetch = async (_url: string, req: any) => { + if ( + req.method === 'eth_getBlockByHash' && + req.params[0] === '0x1850b014065b23d804ecf71a8a4691d076ca87c2e6fb8fe81ee20a4d8e884c24' + ) { + const block = await import(`./testdata/infura15571241wtxns.json`) + return block + } else { + return null // Infura returns null if no block is found + } + } + + const providerUtils = require('@ethereumjs/util/dist/provider') + td.replace(providerUtils, 'fetchFromProvider', fakeFetch) + const blockHash = '0x1850b014065b23d804ecf71a8a4691d076ca87c2e6fb8fe81ee20a4d8e884c24' - const block = await Block.fromEthersProvider(provider, blockHash, { common }) + const block = await Block.fromJsonRpcProvider(provider, blockHash, { common }) t.equal( bytesToPrefixedHexString(block.hash()), blockHash, 'assembled a block from blockdata from a provider' ) + try { + await Block.fromJsonRpcProvider(provider, bytesToPrefixedHexString(randomBytes(32)), {}) + t.fail('should throw') + } catch (err: any) { + t.ok( + err.message.includes('No block data returned from provider'), + 'returned correct error message' + ) + } + td.reset() t.end() }) diff --git a/packages/block/test/mockProvider.ts b/packages/block/test/mockProvider.ts deleted file mode 100644 index ce0f727f5c..0000000000 --- a/packages/block/test/mockProvider.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { ethers } from 'ethers' - -export class MockProvider extends ethers.providers.JsonRpcProvider { - send = async (method: string, params: Array) => { - switch (method) { - case 'eth_getBlockByHash': - return this.getBlockValues(params as any) - case 'eth_chainId': // Always pretends to be mainnet - return 1 - default: - throw new Error(`method ${method} not implemented`) - } - } - - private getBlockValues = async (_params: any) => { - const block = await import(`./testdata/infura15571241wtxns.json`) - return block - } -} diff --git a/packages/client/test/net/peer/libp2pnode.spec.ts b/packages/client/test/net/peer/libp2pnode.spec.ts index 3373417c89..f98c0c8f80 100644 --- a/packages/client/test/net/peer/libp2pnode.spec.ts +++ b/packages/client/test/net/peer/libp2pnode.spec.ts @@ -2,7 +2,7 @@ import * as tape from 'tape' import * as td from 'testdouble' tape('[Libp2pNode]', async (t) => { - const _libp2p = td.replace('libp2p') + td.replace('libp2p') const { Libp2pNode } = await import('../../../lib/net/peer/libp2pnode') t.test('should be a libp2p bundle', (t) => { diff --git a/packages/client/test/net/peer/libp2ppeer.spec.ts b/packages/client/test/net/peer/libp2ppeer.spec.ts index 651c73bd37..2bc598ed39 100644 --- a/packages/client/test/net/peer/libp2ppeer.spec.ts +++ b/packages/client/test/net/peer/libp2ppeer.spec.ts @@ -9,11 +9,11 @@ import type { Libp2pPeer } from '../../../lib/net/peer' import type { Protocol } from '../../../lib/net/protocol' tape('[Libp2pPeer]', async (t) => { - const _PeerId = td.replace('peer-id') + td.replace('peer-id') const Libp2pNode = td.constructor(['start', 'stop', 'dial', 'dialProtocol'] as any) td.replace('../../../lib/net/peer/libp2pnode', { Libp2pNode }) - const Libp2pSender = td.replace('../../../lib/net/protocol/libp2psender') + const Libp2pSender = td.replace('../../../lib/net/protocol/libp2psender') td.when(Libp2pNode.prototype.start()).thenResolve(null) td.when(Libp2pNode.prototype.dial(td.matchers.anything())).thenResolve(null) diff --git a/packages/client/test/net/peerpool.spec.ts b/packages/client/test/net/peerpool.spec.ts index 233986ab26..e5befdfe9f 100644 --- a/packages/client/test/net/peerpool.spec.ts +++ b/packages/client/test/net/peerpool.spec.ts @@ -9,7 +9,7 @@ import { MockPeer } from '../integration/mocks/mockpeer' import type { RlpxServer } from '../../lib/net/server' tape('[PeerPool]', async (t) => { - const Peer = td.replace('../../lib/net/peer/peer', function (this: any, id: string) { + const Peer = td.replace('../../lib/net/peer/peer', function (this: any, id: string) { this.id = id // eslint-disable-line no-invalid-this }) const { PeerPool } = await import('../../lib/net/peerpool') diff --git a/packages/client/test/net/server/libp2pserver.spec.ts b/packages/client/test/net/server/libp2pserver.spec.ts index 14660f4210..71c988d445 100644 --- a/packages/client/test/net/server/libp2pserver.spec.ts +++ b/packages/client/test/net/server/libp2pserver.spec.ts @@ -10,7 +10,7 @@ import { Event } from '../../../lib/types' import { wait } from '../../integration/util' tape('[Libp2pServer]', async (t) => { - const Libp2pPeer = td.replace('../../../lib/net/peer/libp2ppeer') + const Libp2pPeer = td.replace('../../../lib/net/peer/libp2ppeer') Libp2pPeer.id = 'id0' class Libp2pNode extends EventEmitter { diff --git a/packages/devp2p/test/dns.spec.ts b/packages/devp2p/test/dns.spec.ts index eca2f81948..33de000b15 100644 --- a/packages/devp2p/test/dns.spec.ts +++ b/packages/devp2p/test/dns.spec.ts @@ -7,7 +7,7 @@ import * as testdata from './testdata.json' tape('DNS', async (t) => { const mockData = testdata.dns - const mockDns = td.replace('dns') + const mockDns = td.replace('dns') let dns: DNS function initializeDns() { diff --git a/packages/evm/package.json b/packages/evm/package.json index 4e27c4f2ff..8f670b925a 100644 --- a/packages/evm/package.json +++ b/packages/evm/package.json @@ -49,7 +49,6 @@ "dependencies": { "@ethereumjs/common": "^3.1.1", "@ethereumjs/util": "^8.0.5", - "@ethersproject/providers": "^5.7.1", "debug": "^4.3.3", "ethereum-cryptography": "^1.1.2", "mcl-wasm": "^0.7.1", @@ -57,7 +56,6 @@ }, "devDependencies": { "@ethereumjs/statemanager": "^1.0.4", - "@ethersproject/abi": "^5.0.12", "@types/benchmark": "^1.0.33", "@types/core-js": "^2.5.0", "@types/lru-cache": "^5.1.0", diff --git a/packages/statemanager/test/ethersStateManager.spec.ts b/packages/statemanager/test/ethersStateManager.spec.ts index fbbe541878..9953f6a15a 100644 --- a/packages/statemanager/test/ethersStateManager.spec.ts +++ b/packages/statemanager/test/ethersStateManager.spec.ts @@ -36,7 +36,7 @@ tape('Ethers State Manager initialization tests', (t) => { state = new EthersStateManager({ provider, blockTag: 1n }) t.equal((state as any).blockTag, '0x1', 'State Manager instantiated with predefined blocktag') - state = new EthersStateManager({ provider: 'http://localhost:8545', blockTag: 1n }) + state = new EthersStateManager({ provider: 'https://google.com', blockTag: 1n }) t.ok(state instanceof EthersStateManager, 'was able to instantiate state manager with valid url') const invalidProvider = new BaseProvider('mainnet') @@ -145,7 +145,7 @@ tape('Ethers State Manager API tests', async (t) => { t.ok(await state.accountExists(vitalikDotEth), 'account should not exist after being deleted') try { - await Block.fromEthersProvider(provider, 'fakeBlockTag', {} as any) + await Block.fromJsonRpcProvider(provider, 'fakeBlockTag', {} as any) t.fail('should have thrown') } catch (err: any) { t.ok( @@ -224,8 +224,8 @@ tape('runTx test: replay mainnet transactions', async (t) => { const blockTag = 15496077n common.setHardforkByBlockNumber(blockTag) - const txHash = '0xed1960aa7d0d7b567c946d94331dddb37a1c67f51f30bf51f256ea40db88cfb0' - const tx = await TransactionFactory.fromEthersProvider(provider, txHash, { common }) + const txData = require('./testdata/providerData/transactions/0xed1960aa7d0d7b567c946d94331dddb37a1c67f51f30bf51f256ea40db88cfb0.json') + const tx = await TransactionFactory.fromRPCTx(txData, { common }) const state = new EthersStateManager({ provider, // Set the state manager to look at the state of the chain before the block has been executed @@ -260,7 +260,8 @@ tape('runBlock test', async (t) => { common.setHardforkByBlockNumber(blockTag - 1n) const vm = await VM.create({ common, stateManager: state }) - const block = await Block.fromEthersProvider(provider, blockTag, { common }) + const blockData = require('./testdata/providerData/blocks/block0x7a120.json') + const block = Block.fromRPC(blockData, [], { common }) try { const res = await vm.runBlock({ block, diff --git a/packages/tx/README.md b/packages/tx/README.md index 6e218dfaa0..801cc9c355 100644 --- a/packages/tx/README.md +++ b/packages/tx/README.md @@ -282,7 +282,7 @@ The correct tx type class for instantiation will then be chosen on runtime based - `public static fromTxData(txData: TxData | AccessListEIP2930TxData, txOptions: TxOptions = {}): TypedTransaction` - `public static fromSerializedData(data: Buffer, txOptions: TxOptions = {}): TypedTransaction` - `public static fromBlockBodyData(data: Buffer | Buffer[], txOptions: TxOptions = {})` -- `public static async fromEthersProvider(provider: string | ethers.providers.JsonRpcProvider, txHash: string, txOptions?: TxOptions)` +- `public static async fromJsonRpcProvider(provider: string | EthersProvider, txHash: string, txOptions?: TxOptions)` ### Sending a Transaction diff --git a/packages/tx/package.json b/packages/tx/package.json index 77e01e934a..b8c4c502ad 100644 --- a/packages/tx/package.json +++ b/packages/tx/package.json @@ -55,8 +55,7 @@ "@ethereumjs/common": "^3.1.1", "@ethereumjs/rlp": "^4.0.1", "@ethereumjs/util": "^8.0.5", - "ethereum-cryptography": "^1.1.2", - "@ethersproject/providers": "^5.7.2" + "ethereum-cryptography": "^1.1.2" }, "peerDependencies": { "c-kzg": "^2.0.4" @@ -70,7 +69,8 @@ "@types/minimist": "^1.2.0", "@types/node-dir": "^0.0.34", "minimist": "^1.2.0", - "node-dir": "^0.1.16" + "node-dir": "^0.1.16", + "testdouble": "^3.17.2" }, "engines": { "node": ">=14" diff --git a/packages/tx/src/transactionFactory.ts b/packages/tx/src/transactionFactory.ts index 7777b4897c..c169006359 100644 --- a/packages/tx/src/transactionFactory.ts +++ b/packages/tx/src/transactionFactory.ts @@ -1,5 +1,4 @@ -import { bytesToBigInt, toBytes } from '@ethereumjs/util' -import { JsonRpcProvider } from '@ethersproject/providers' +import { bytesToBigInt, fetchFromProvider, getProvider, toBytes } from '@ethereumjs/util' import { FeeMarketEIP1559Transaction } from './eip1559Transaction' import { AccessListEIP2930Transaction } from './eip2930Transaction' @@ -15,6 +14,7 @@ import type { TxOptions, TypedTransaction, } from './types' +import type { EthersProvider } from '@ethereumjs/util' export class TransactionFactory { // It is not possible to instantiate a TransactionFactory object. @@ -95,18 +95,24 @@ export class TransactionFactory { /** * Method to retrieve a transaction from the provider - * @param provider - An Ethers JsonRPCProvider + * @param provider - a url string for a JSON-RPC provider or an Ethers JsonRPCProvider object * @param txHash - Transaction hash * @param txOptions - The transaction options * @returns the transaction specified by `txHash` */ - public static async fromEthersProvider( - provider: string | JsonRpcProvider, + public static async fromJsonRpcProvider( + provider: string | EthersProvider, txHash: string, txOptions?: TxOptions ) { - const prov = typeof provider === 'string' ? new JsonRpcProvider(provider) : provider - const txData = await prov.send('eth_getTransactionByHash', [txHash]) + const prov = getProvider(provider) + const txData = await fetchFromProvider(prov, { + method: 'eth_getTransactionByHash', + params: [txHash], + }) + if (txData === null) { + throw new Error('No data returned from provider') + } return TransactionFactory.fromRPCTx(txData, txOptions) } diff --git a/packages/tx/test/fromRpc.spec.ts b/packages/tx/test/fromRpc.spec.ts index 9e10c1da7c..250797bfa7 100644 --- a/packages/tx/test/fromRpc.spec.ts +++ b/packages/tx/test/fromRpc.spec.ts @@ -1,26 +1,53 @@ import { Chain, Common, Hardfork } from '@ethereumjs/common' -import { bytesToHex, bytesToPrefixedHexString } from '@ethereumjs/util' +import { bytesToHex, bytesToPrefixedHexString, randomBytes } from '@ethereumjs/util' import * as tape from 'tape' +import * as td from 'testdouble' import { TransactionFactory } from '../src' import { normalizeTxParams } from '../src/fromRpc' -import { MockProvider } from './mockProvider' - const optimismTx = require('./json/optimismTx.json') const txTypes = [0, 1, 2] -tape('[fromEthersProvider]', async (t) => { +tape('[fromJsonRpcProvider]', async (t) => { + const fakeFetch = async (_url: string, req: any) => { + if ( + req.method === 'eth_getTransactionByHash' && + req.params[0] === '0xed1960aa7d0d7b567c946d94331dddb37a1c67f51f30bf51f256ea40db88cfb0' + ) { + const txData = await import(`./json/rpcTx.json`) + return txData + } else { + return null // This is the value Infura returns if no transaction is found matching the provided hash + } + } + const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.London }) - const provider = new MockProvider() + const provider = 'https://my.json.rpc.provider.com:8545' + const providerUtils = require('@ethereumjs/util/dist/provider') + td.replace(providerUtils, 'fetchFromProvider', fakeFetch) const txHash = '0xed1960aa7d0d7b567c946d94331dddb37a1c67f51f30bf51f256ea40db88cfb0' - const tx = await TransactionFactory.fromEthersProvider(provider, txHash, { common }) + const tx = await TransactionFactory.fromJsonRpcProvider(provider, txHash, { common }) t.equal( bytesToPrefixedHexString(tx.hash()), txHash, 'generated correct tx from transaction RPC data' ) + try { + await TransactionFactory.fromJsonRpcProvider( + provider, + bytesToPrefixedHexString(randomBytes(32)), + {} + ) + t.fail('should throw') + } catch (err: any) { + t.ok( + err.message.includes('No data returned from provider'), + 'throws correct error when no tx returned' + ) + } + td.reset() t.end() }) diff --git a/packages/tx/test/mockProvider.ts b/packages/tx/test/mockProvider.ts deleted file mode 100644 index d0ae136fce..0000000000 --- a/packages/tx/test/mockProvider.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { JsonRpcProvider } from '@ethersproject/providers' - -export class MockProvider extends JsonRpcProvider { - send = async (method: string, params: Array) => { - switch (method) { - case 'eth_chainId': // Always pretends to be mainnet - return 1 - case 'eth_getTransactionByHash': - return this.getTransactionData(params as any) - default: - throw new Error(`method ${method} not implemented`) - } - } - - private getTransactionData = async (_params: [txHash: string]) => { - const txData = await import(`./json/rpcTx.json`) - return txData - } -} diff --git a/packages/util/src/index.ts b/packages/util/src/index.ts index 9a05428d06..b3cbbf3656 100644 --- a/packages/util/src/index.ts +++ b/packages/util/src/index.ts @@ -67,3 +67,4 @@ export { } from './internal' export * from './kzg' export * from './lock' +export * from './provider' diff --git a/packages/util/src/provider.ts b/packages/util/src/provider.ts new file mode 100644 index 0000000000..d344037e4c --- /dev/null +++ b/packages/util/src/provider.ts @@ -0,0 +1,90 @@ +import * as https from 'https' + +type rpcParams = { + method: string + params: (string | boolean | number)[] +} + +const nodeFetch = async (url: string, data: string) => + new Promise((resolve, reject) => { + const options = { + method: 'POST', + headers: { + 'content-type': 'application/json', + }, + } + + const req = https + .request(url, options, (resp) => { + let data = '' + resp.on('data', (chunk) => { + data += chunk + }) + resp.on('end', () => { + const res = JSON.parse(data) + resolve(res) + }) + }) + .on('error', (err) => { + reject(err.message) + }) + req.end(data) + }) + +/** + * Makes a simple RPC call to a remote Ethereum JSON-RPC provider and passes through the response. + * No parameter or response validation is done. + * + * @param url the URL for the JSON RPC provider + * @param params the parameters for the JSON-RPC method - refer to + * https://ethereum.org/en/developers/docs/apis/json-rpc/ for details on RPC methods + * @returns the `result` field from the JSON-RPC response + */ +export const fetchFromProvider = async (url: string, params: rpcParams) => { + const data = JSON.stringify({ + method: params.method, + params: params.params, + jsonrpc: '2.0', + id: 1, + }) + if (global.fetch !== undefined) { + const res = await fetch(url, { + headers: { + 'content-type': 'application/json', + }, + method: 'POST', + body: data, + }) + const json = await res.json() + return json.result + } else { + const res: any = await nodeFetch(url, data) + return res.result + } +} + +/** + * + * @param provider a URL string or {@link EthersProvider} + * @returns the extracted URL string for the JSON-RPC Provider + */ +export const getProvider = (provider: string | EthersProvider) => { + if (typeof provider === 'string') { + return provider + } else if (typeof provider === 'object' && provider.connection.url !== undefined) { + return provider.connection.url + } else { + throw new Error('Must provide valid provider URL or Web3Provider') + } +} + +/** + * A partial interface for an `ethers` `JsonRpcProvider` + * We only use the url string since we do raw `fetch` or `http` calls to + * retrieve the necessary data + */ +export interface EthersProvider { + connection: { + url: string + } +} diff --git a/packages/util/test/provider.spec.ts b/packages/util/test/provider.spec.ts new file mode 100644 index 0000000000..d14a69473b --- /dev/null +++ b/packages/util/test/provider.spec.ts @@ -0,0 +1,43 @@ +import * as tape from 'tape' + +import { fetchFromProvider, getProvider } from '../src' + +const providerUrl = 'https://myfakeprovider.com' +const fakeEthersProvider = { + connection: { + url: 'https://myfakeethersprovider.com/rpc', + }, +} +tape('getProvider', (t) => { + t.equal(getProvider(providerUrl), providerUrl, 'returned correct provider url string') + t.equal( + getProvider(fakeEthersProvider), + fakeEthersProvider.connection.url, + 'returned correct provider url string' + ) + t.throws( + () => getProvider(1), + (err: any) => err.message.includes('Must provide valid provider URL or Web3Provider'), + 'throws correct error' + ) + t.end() +}) + +tape('fetchFromProvider', async (t) => { + try { + await fetchFromProvider(providerUrl, { + method: 'eth_getBalance', + params: ['0xabcd'], + }) + t.fail('should throw') + } catch (err: any) { + if (global.fetch !== undefined) { + t.ok(err.message.includes('fetch'), 'tried to fetch and failed') + } else { + t.ok( + err.toString().includes(providerUrl.split('//')[1]), + 'tries to fetch from specified provider url' + ) + } + } +}) From 9b85ff1e7c3f5b048d1dca498b5af26f4ccc3e7a Mon Sep 17 00:00:00 2001 From: Holger Drewes Date: Thu, 4 May 2023 08:52:14 +0200 Subject: [PATCH 29/53] Client Memory Optimizations (#2675) * StateManager: swap LRU_CACHE with ORDERED_MAP cache on copy(), add dedicated generic stateManager.spec.ts file, add copy() tests * Trie: deactivate cache on copy(), add test * Client: more cautious account and trie cache defaults * Client: add simple memory stats * dynamically load v8 for mem stats * exlude v8 from karma builds * Client: new execution option allowing to skip execution * refac execution trigger and log experience --------- Co-authored-by: harkamal --- packages/client/bin/cli.ts | 6 ++ packages/client/karma.conf.js | 2 +- packages/client/lib/config.ts | 12 +++- packages/client/lib/execution/vmexecution.ts | 69 ++++++++++++++++--- .../client/lib/service/fullethereumservice.ts | 4 +- packages/client/lib/sync/beaconsync.ts | 8 ++- packages/client/lib/sync/fullsync.ts | 8 ++- packages/client/lib/types.ts | 1 + packages/client/lib/util/index.ts | 13 ++++ packages/statemanager/src/stateManager.ts | 27 ++++++-- .../test/stateManager.account.spec.ts | 9 --- .../statemanager/test/statemanager.spec.ts | 50 ++++++++++++++ packages/trie/src/trie/trie.ts | 9 +++ packages/trie/test/trie/checkpoint.spec.ts | 7 ++ 14 files changed, 193 insertions(+), 32 deletions(-) create mode 100644 packages/statemanager/test/statemanager.spec.ts diff --git a/packages/client/bin/cli.ts b/packages/client/bin/cli.ts index b454db5e91..00648129ff 100755 --- a/packages/client/bin/cli.ts +++ b/packages/client/bin/cli.ts @@ -236,6 +236,11 @@ const args: ClientOpts = yargs(hideBin(process.argv)) describe: 'EIP-1459 ENR tree urls to query for peer discovery targets', array: true, }) + .option('execution', { + describe: 'Start continuous VM execution (pre-Merge setting)', + boolean: true, + default: Config.EXECUTION, + }) .option('numBlocksPerIteration', { describe: 'Number of blocks to execute in batch mode and logged to console', number: true, @@ -738,6 +743,7 @@ async function run() { discDns: args.discDns, discV4: args.discV4, dnsAddr: args.dnsAddr, + execution: args.execution, numBlocksPerIteration: args.numBlocksPerIteration, accountCache: args.accountCache, storageCache: args.storageCache, diff --git a/packages/client/karma.conf.js b/packages/client/karma.conf.js index 10532bf0e5..f9bcfe6839 100644 --- a/packages/client/karma.conf.js +++ b/packages/client/karma.conf.js @@ -17,7 +17,7 @@ module.exports = function (config) { ecmaVersion: 12, }, // sourceMap: true, - exclude: ['async_hooks'], + exclude: ['async_hooks', 'node:v8'], resolve: { alias: { // Hotfix for `multiformats` client browser build error in Node 16, #1346, 2021-07-12 diff --git a/packages/client/lib/config.ts b/packages/client/lib/config.ts index ecd98534c1..6ca51d207a 100644 --- a/packages/client/lib/config.ts +++ b/packages/client/lib/config.ts @@ -189,6 +189,11 @@ export interface ConfigOptions { */ dnsNetworks?: string[] + /** + * Start continuous VM execution (pre-Merge setting) + */ + execution?: boolean + /** * Number of blocks to execute in batch mode and logged to console */ @@ -310,10 +315,11 @@ export class Config { public static readonly MINPEERS_DEFAULT = 1 public static readonly MAXPEERS_DEFAULT = 25 public static readonly DNSADDR_DEFAULT = '8.8.8.8' + public static readonly EXECUTION = true public static readonly NUM_BLOCKS_PER_ITERATION = 100 - public static readonly ACCOUNT_CACHE = 1000000 + public static readonly ACCOUNT_CACHE = 400000 public static readonly STORAGE_CACHE = 200000 - public static readonly TRIE_CACHE = 500000 + public static readonly TRIE_CACHE = 200000 public static readonly DEBUGCODE_DEFAULT = false public static readonly SAFE_REORG_DISTANCE = 100 public static readonly SKELETON_FILL_CANONICAL_BACKSTEP = 100 @@ -345,6 +351,7 @@ export class Config { public readonly minPeers: number public readonly maxPeers: number public readonly dnsAddr: string + public readonly execution: boolean public readonly numBlocksPerIteration: number public readonly accountCache: number public readonly storageCache: number @@ -402,6 +409,7 @@ export class Config { this.minPeers = options.minPeers ?? Config.MINPEERS_DEFAULT this.maxPeers = options.maxPeers ?? Config.MAXPEERS_DEFAULT this.dnsAddr = options.dnsAddr ?? Config.DNSADDR_DEFAULT + this.execution = options.execution ?? Config.EXECUTION this.numBlocksPerIteration = options.numBlocksPerIteration ?? Config.NUM_BLOCKS_PER_ITERATION this.accountCache = options.accountCache ?? Config.ACCOUNT_CACHE this.storageCache = options.storageCache ?? Config.STORAGE_CACHE diff --git a/packages/client/lib/execution/vmexecution.ts b/packages/client/lib/execution/vmexecution.ts index 8211862411..65aa39b1d7 100644 --- a/packages/client/lib/execution/vmexecution.ts +++ b/packages/client/lib/execution/vmexecution.ts @@ -12,19 +12,23 @@ import { Lock, bytesToHex, bytesToPrefixedHexString, equalsBytes } from '@ethere import { VM } from '@ethereumjs/vm' import { Event } from '../types' -import { short } from '../util' +import { getV8Engine, short } from '../util' import { debugCodeReplayBlock } from '../util/debug' import { Execution } from './execution' import { LevelDB } from './level' import { ReceiptsManager } from './receipt' +import type { V8Engine } from '../util' import type { ExecutionOptions } from './execution' import type { Block } from '@ethereumjs/block' import type { RunBlockOpts, TxReceipt } from '@ethereumjs/vm' export class VMExecution extends Execution { private _lock = new Lock() + // A handle to v8Engine lib for mem stats, assigned on open if running in node + private v8Engine: V8Engine | null = null + public vm: VM public hardfork: string = '' @@ -38,8 +42,8 @@ export class VMExecution extends Execution { /** * Display state cache stats every num blocks */ - private CACHE_STATS_NUM_BLOCKS = 500 - private cacheStatsCount = 0 + private STATS_NUM_BLOCKS = 500 + private statsCount = 0 /** * Create new VM execution module @@ -117,6 +121,11 @@ export class VMExecution extends Execution { if (this.started || this.vmPromise !== undefined) { return } + + if (this.v8Engine === null) { + this.v8Engine = await getV8Engine() + } + await this.vm.init() if (typeof this.vm.blockchain.getIteratorHead !== 'function') { throw new Error('cannot get iterator head: blockchain has no getIteratorHead function') @@ -342,7 +351,7 @@ export class VMExecution extends Execution { throw Error('Execution stopped') } const beforeTS = Date.now() - this.cacheStats(this.vm) + this.stats(this.vm) const result = await this.vm.runBlock({ block, root: parentState, @@ -471,6 +480,40 @@ export class VMExecution extends Execution { return numExecuted ?? 0 } + /** + * Start execution + */ + async start(): Promise { + const { blockchain } = this.vm + if (this.running || !this.started) { + return false + } + + if (typeof blockchain.getIteratorHead !== 'function') { + throw new Error('cannot get iterator head: blockchain has no getIteratorHead function') + } + const vmHeadBlock = await blockchain.getIteratorHead() + if (typeof blockchain.getCanonicalHeadBlock !== 'function') { + throw new Error('cannot get iterator head: blockchain has no getCanonicalHeadBlock function') + } + const canonicalHead = await blockchain.getCanonicalHeadBlock() + + const infoStr = `vmHead=${vmHeadBlock.header.number} canonicalHead=${ + canonicalHead.header.number + } hardfork=${this.config.execCommon.hardfork()} execution=${this.config.execution}` + if ( + !this.config.execCommon.gteHardfork(Hardfork.Paris) && + this.config.execution && + vmHeadBlock.header.number < canonicalHead.header.number + ) { + this.config.logger.info(`Starting execution run ${infoStr}`) + void this.run(true, true) + } else { + this.config.logger.info(`Skipped execution run ${infoStr}`) + } + return true + } + /** * Stop VM execution. Returns a promise that resolves once its stopped. */ @@ -523,7 +566,7 @@ export class VMExecution extends Execution { // we are skipping header validation because the block has been picked from the // blockchain and header should have already been validated while putBlock const beforeTS = Date.now() - this.cacheStats(vm) + this.stats(vm) const res = await vm.runBlock({ block, root, @@ -566,9 +609,9 @@ export class VMExecution extends Execution { } } - cacheStats(vm: VM) { - this.cacheStatsCount += 1 - if (this.cacheStatsCount === this.CACHE_STATS_NUM_BLOCKS) { + stats(vm: VM) { + this.statsCount += 1 + if (this.statsCount === this.STATS_NUM_BLOCKS) { let stats = (vm.stateManager as any)._accountCache.stats() this.config.logger.info( `Account cache stats size=${stats.size} reads=${stats.reads} hits=${stats.hits} writes=${stats.writes}` @@ -582,7 +625,15 @@ export class VMExecution extends Execution { `Trie cache stats size=${tStats.size} reads=${tStats.cache.reads} hits=${tStats.cache.hits} ` + `writes=${tStats.cache.writes} readsDB=${tStats.db.reads} hitsDB=${tStats.db.hits} writesDB=${tStats.db.writes}` ) - this.cacheStatsCount = 0 + + if (this.v8Engine !== null) { + const { used_heap_size, heap_size_limit } = this.v8Engine.getHeapStatistics() + + const heapUsed = Math.round(used_heap_size / 1000 / 1000) // MB + const percentage = Math.round((100 * used_heap_size) / heap_size_limit) + this.config.logger.info(`Memory stats usage=${heapUsed} MB percentage=${percentage}%`) + } + this.statsCount = 0 } } } diff --git a/packages/client/lib/service/fullethereumservice.ts b/packages/client/lib/service/fullethereumservice.ts index a8ea53d227..ba4434b3e9 100644 --- a/packages/client/lib/service/fullethereumservice.ts +++ b/packages/client/lib/service/fullethereumservice.ts @@ -162,9 +162,7 @@ export class FullEthereumService extends EthereumService { } await super.start() this.miner?.start() - if (!this.config.execCommon.gteHardfork(Hardfork.Paris)) { - void this.execution.run(true, true) - } + await this.execution.start() return true } diff --git a/packages/client/lib/sync/beaconsync.ts b/packages/client/lib/sync/beaconsync.ts index c67705c06a..990b2cf05e 100644 --- a/packages/client/lib/sync/beaconsync.ts +++ b/packages/client/lib/sync/beaconsync.ts @@ -69,7 +69,9 @@ export class BeaconSynchronizer extends Synchronizer { await this.skeleton.open() this.config.events.on(Event.SYNC_FETCHED_BLOCKS, this.processSkeletonBlocks) - this.config.events.on(Event.CHAIN_UPDATED, this.runExecution) + if (this.config.execution) { + this.config.events.on(Event.CHAIN_UPDATED, this.runExecution) + } const { height: number, td } = this.chain.blocks const hash = this.chain.blocks.latest!.hash() @@ -331,7 +333,9 @@ export class BeaconSynchronizer extends Synchronizer { async close() { if (!this.opened) return this.config.events.removeListener(Event.SYNC_FETCHED_BLOCKS, this.processSkeletonBlocks) - this.config.events.removeListener(Event.CHAIN_UPDATED, this.runExecution) + if (this.config.execution) { + this.config.events.removeListener(Event.CHAIN_UPDATED, this.runExecution) + } await super.close() } } diff --git a/packages/client/lib/sync/fullsync.ts b/packages/client/lib/sync/fullsync.ts index a76cb77d28..8ee2748276 100644 --- a/packages/client/lib/sync/fullsync.ts +++ b/packages/client/lib/sync/fullsync.ts @@ -75,7 +75,9 @@ export class FullSynchronizer extends Synchronizer { this.config.events.on(Event.SYNC_FETCHED_BLOCKS, this.processBlocks) this.config.events.on(Event.SYNC_EXECUTION_VM_ERROR, this.stop) - this.config.events.on(Event.CHAIN_UPDATED, this.runExecution) + if (this.config.execution) { + this.config.events.on(Event.CHAIN_UPDATED, this.runExecution) + } await this.pool.open() const { height: number, td } = this.chain.blocks @@ -404,7 +406,9 @@ export class FullSynchronizer extends Synchronizer { async stop(): Promise { this.config.events.removeListener(Event.SYNC_FETCHED_BLOCKS, this.processBlocks) this.config.events.removeListener(Event.SYNC_EXECUTION_VM_ERROR, this.stop) - this.config.events.removeListener(Event.CHAIN_UPDATED, this.runExecution) + if (this.config.execution) { + this.config.events.removeListener(Event.CHAIN_UPDATED, this.runExecution) + } return super.stop() } diff --git a/packages/client/lib/types.ts b/packages/client/lib/types.ts index 6c32062fb1..6b2f749e08 100644 --- a/packages/client/lib/types.ts +++ b/packages/client/lib/types.ts @@ -143,6 +143,7 @@ export interface ClientOpts { minPeers?: number maxPeers?: number dnsAddr?: string + execution?: boolean numBlocksPerIteration?: number accountCache?: number storageCache?: number diff --git a/packages/client/lib/util/index.ts b/packages/client/lib/util/index.ts index 755880a66b..9a56762925 100644 --- a/packages/client/lib/util/index.ts +++ b/packages/client/lib/util/index.ts @@ -56,3 +56,16 @@ export function timeDiff(timestamp: number) { const diff = new Date().getTime() / 1000 - timestamp return timeDuration(diff) } + +// Dynamically load v8 for tracking mem stats +const isBrowser = new Function('try {return this===window;}catch(e){ return false;}') +export type V8Engine = { + getHeapStatistics: () => { heap_size_limit: number; used_heap_size: number } +} +let v8Engine: V8Engine | null = null +export async function getV8Engine(): Promise { + if (isBrowser() === false && v8Engine === null) { + v8Engine = (await import('node:v8')) as V8Engine + } + return v8Engine +} diff --git a/packages/statemanager/src/stateManager.ts b/packages/statemanager/src/stateManager.ts index 5d13602888..94f4a93aa3 100644 --- a/packages/statemanager/src/stateManager.ts +++ b/packages/statemanager/src/stateManager.ts @@ -789,13 +789,32 @@ export class DefaultStateManager implements StateManager { * Copies the current instance of the `StateManager` * at the last fully committed point, i.e. as if all current * checkpoints were reverted. + * + * Note on caches: + * 1. For caches instantiated as an LRU cache type + * the copy() method will instantiate with an ORDERED_MAP cache + * instead, since copied instantances are mostly used in + * short-term usage contexts and LRU cache instantation would create + * a large overhead here. + * 2. Cache values are generally not copied along */ copy(): StateManager { + const trie = this._trie.copy(false) + const prefixCodeHashes = this._prefixCodeHashes + let accountCacheOpts = { ...this._accountCacheSettings } + if (!this._accountCacheSettings.deactivate) { + accountCacheOpts = { ...accountCacheOpts, type: CacheType.ORDERED_MAP } + } + let storageCacheOpts = { ...this._storageCacheSettings } + if (!this._storageCacheSettings.deactivate) { + storageCacheOpts = { ...storageCacheOpts, type: CacheType.ORDERED_MAP } + } + return new DefaultStateManager({ - trie: this._trie.copy(false), - prefixCodeHashes: this._prefixCodeHashes, - accountCacheOpts: this._accountCacheSettings, - storageCacheOpts: this._storageCacheSettings, + trie, + prefixCodeHashes, + accountCacheOpts, + storageCacheOpts, }) } diff --git a/packages/statemanager/test/stateManager.account.spec.ts b/packages/statemanager/test/stateManager.account.spec.ts index 9d0b98aa26..6bfb3df5e4 100644 --- a/packages/statemanager/test/stateManager.account.spec.ts +++ b/packages/statemanager/test/stateManager.account.spec.ts @@ -10,15 +10,6 @@ import { createAccount } from './util' tape('StateManager -> General/Account', (t) => { for (const accountCacheOpts of [{ deactivate: false }, { deactivate: true }]) { - t.test('should instantiate', async (st) => { - const stateManager = new DefaultStateManager({ accountCacheOpts }) - - st.deepEqual(stateManager._trie.root(), KECCAK256_RLP, 'it has default root') - const res = await stateManager.getStateRoot() - st.deepEqual(res, KECCAK256_RLP, 'it has default root') - st.end() - }) - t.test('should set the state root to empty', async (st) => { const stateManager = new DefaultStateManager({ accountCacheOpts }) st.ok(equalsBytes(stateManager._trie.root(), KECCAK256_RLP), 'it has default root') diff --git a/packages/statemanager/test/statemanager.spec.ts b/packages/statemanager/test/statemanager.spec.ts new file mode 100644 index 0000000000..935c828cae --- /dev/null +++ b/packages/statemanager/test/statemanager.spec.ts @@ -0,0 +1,50 @@ +import { KECCAK256_RLP } from '@ethereumjs/util' +import * as tape from 'tape' + +import { CacheType, DefaultStateManager } from '../src' + +tape('StateManager -> General', (t) => { + t.test('should instantiate', async (st) => { + const sm = new DefaultStateManager() + + st.deepEqual(sm._trie.root(), KECCAK256_RLP, 'it has default root') + const res = await sm.getStateRoot() + st.deepEqual(res, KECCAK256_RLP, 'it has default root') + st.end() + }) + + t.test('copy()', async (st) => { + let sm = new DefaultStateManager({ + prefixCodeHashes: false, + }) + + let smCopy = sm.copy() + st.equal( + (smCopy as any)._prefixCodeHashes, + (sm as any)._prefixCodeHashes, + 'should retain non-default values' + ) + + sm = new DefaultStateManager({ + accountCacheOpts: { + type: CacheType.LRU, + }, + storageCacheOpts: { + type: CacheType.LRU, + }, + }) + + smCopy = sm.copy() + st.equal( + (smCopy as any)._accountCacheSettings.type, + CacheType.ORDERED_MAP, + 'should switch to ORDERED_MAP account cache on copy()' + ) + st.equal( + (smCopy as any)._storageCacheSettings.type, + CacheType.ORDERED_MAP, + 'should switch to ORDERED_MAP storage cache on copy()' + ) + st.end() + }) +}) diff --git a/packages/trie/src/trie/trie.ts b/packages/trie/src/trie/trie.ts index 6c01279958..58e5393003 100644 --- a/packages/trie/src/trie/trie.ts +++ b/packages/trie/src/trie/trie.ts @@ -858,6 +858,14 @@ export class Trie { /** * Returns a copy of the underlying trie. + * + * Note on db: the copy will create a reference to the + * same underlying database. + * + * Note on cache: for memory reasons a copy will not + * recreate a new LRU cache but initialize with cache + * being deactivated. + * * @param includeCheckpoints - If true and during a checkpoint, the copy will contain the checkpointing metadata and will use the same scratch as underlying db. */ copy(includeCheckpoints = true): Trie { @@ -865,6 +873,7 @@ export class Trie { ...this._opts, db: this._db.db.copy(), root: this.root(), + cacheSize: 0, }) if (includeCheckpoints && this.hasCheckpoints()) { trie._db.setCheckpoints(this._db.checkpoints) diff --git a/packages/trie/test/trie/checkpoint.spec.ts b/packages/trie/test/trie/checkpoint.spec.ts index ebd737adfe..6d666fecb8 100644 --- a/packages/trie/test/trie/checkpoint.spec.ts +++ b/packages/trie/test/trie/checkpoint.spec.ts @@ -31,6 +31,13 @@ tape('testing checkpoints', function (tester) { t.end() }) + it('should deactivate cache on copy()', async function (t) { + const trie = new Trie({ cacheSize: 100 }) + trieCopy = trie.copy() + t.equal((trieCopy as any)._opts.cacheSize, 0) + t.end() + }) + it('should create a checkpoint', function (t) { trie.checkpoint() t.ok(trie.hasCheckpoints()) From e4075b5241caf94d6fce705afd34c12de38ae9f3 Mon Sep 17 00:00:00 2001 From: g11tech Date: Thu, 4 May 2023 13:11:02 +0530 Subject: [PATCH 30/53] client: Fix unclean shutdown scenario where SIGINT may come before client fully started (#2677) --- packages/client/bin/cli.ts | 48 +++++++++++++++++++++++++++----------- 1 file changed, 34 insertions(+), 14 deletions(-) diff --git a/packages/client/bin/cli.ts b/packages/client/bin/cli.ts index 00648129ff..1133c0f351 100755 --- a/packages/client/bin/cli.ts +++ b/packages/client/bin/cli.ts @@ -785,22 +785,42 @@ async function run() { config.logger.info(`Reading custom genesis state accounts=${numAccounts}`) } - const client = await startClient(config, customGenesisState) - const servers = - args.rpc === true || args.rpcEngine === true ? startRPCServers(client, args as RPCArgs) : [] - if ( - client.config.chainCommon.gteHardfork(Hardfork.Paris) === true && - (args.rpcEngine === false || args.rpcEngine === undefined) - ) { - config.logger.warn(`Engine RPC endpoint not activated on a post-Merge HF setup.`) - } + // Do not wait for client to be fully started so that we can hookup SIGINT handling + // else a SIGINT before may kill the process in unclean manner + const clientStartPromise = startClient(config, customGenesisState) + .then((client) => { + const servers = + args.rpc === true || args.rpcEngine === true ? startRPCServers(client, args as RPCArgs) : [] + if ( + client.config.chainCommon.gteHardfork(Hardfork.Paris) === true && + (args.rpcEngine === false || args.rpcEngine === undefined) + ) { + config.logger.warn(`Engine RPC endpoint not activated on a post-Merge HF setup.`) + } + config.logger.info('Client started successfully') + return { client, servers } + }) + .catch((e) => { + config.logger.error('Error starting client', e) + return null + }) + process.on('SIGINT', async () => { - config.logger.info('Caught interrupt signal. Shutting down...') - for (const s of servers) { - s.http().close() + config.logger.info('Caught interrupt signal. Obtaining client handle for clean shutdown...') + config.logger.info('(This might take a little longer if client not yet fully started)') + const clientHandle = await clientStartPromise + if (clientHandle !== null) { + config.logger.info('Shutting down the client and the servers...') + const { client, servers } = clientHandle + for (const s of servers) { + s.http().close() + } + await client.stop() + config.logger.info('Exiting.') + } else { + config.logger.info('Client did not start properly, exiting ...') } - await client.stop() - config.logger.info('Exiting.') + process.exit() }) } From 264848e2f27df8bb109bca9558e6c419f5612915 Mon Sep 17 00:00:00 2001 From: g11tech Date: Fri, 5 May 2023 23:31:01 +0530 Subject: [PATCH 31/53] blockchain: Save iterator head to last successfuly executed even on errors (#2680) * blockchain: Save iterator head to last successfuly executed even on errors * comment * fix comment spelling * do not assign head on reorg * fix comment --------- Co-authored-by: acolytec3 <17355484+acolytec3@users.noreply.github.com> --- packages/blockchain/src/blockchain.ts | 81 +++--- packages/client/lib/execution/vmexecution.ts | 269 ++++++++++--------- packages/client/lib/util/debug.ts | 2 +- 3 files changed, 193 insertions(+), 159 deletions(-) diff --git a/packages/blockchain/src/blockchain.ts b/packages/blockchain/src/blockchain.ts index 9b7280ad56..0e1ae42477 100644 --- a/packages/blockchain/src/blockchain.ts +++ b/packages/blockchain/src/blockchain.ts @@ -981,44 +981,61 @@ export class Blockchain implements BlockchainInterface { let blocksRanCounter = 0 let lastBlock: Block | undefined - while (maxBlocks !== blocksRanCounter) { - try { - let nextBlock = await this.getBlock(nextBlockNumber) - const reorg = lastBlock - ? !equalsBytes(lastBlock.hash(), nextBlock.header.parentHash) - : false - if (reorg) { - // If reorg has happened, the _heads must have been updated so lets reload the counters - headHash = this._heads[name] ?? this.genesisBlock.hash() - headBlockNumber = await this.dbManager.hashToNumber(headHash) - nextBlockNumber = headBlockNumber + BigInt(1) - nextBlock = await this.getBlock(nextBlockNumber) - } - this._heads[name] = nextBlock.hash() - lastBlock = nextBlock - if (releaseLockOnCallback === true) { - this._lock.release() - } + try { + while (maxBlocks !== blocksRanCounter) { try { - await onBlock(nextBlock, reorg) - } finally { + let nextBlock = await this.getBlock(nextBlockNumber) + const reorg = lastBlock + ? !equalsBytes(lastBlock.hash(), nextBlock.header.parentHash) + : false + if (reorg) { + // If reorg has happened, the _heads must have been updated so lets reload the counters + headHash = this._heads[name] ?? this.genesisBlock.hash() + headBlockNumber = await this.dbManager.hashToNumber(headHash) + nextBlockNumber = headBlockNumber + BigInt(1) + nextBlock = await this.getBlock(nextBlockNumber) + } + + // While running onBlock with released lock, reorgs can happen via putBlocks + let reorgWhileOnBlock = false if (releaseLockOnCallback === true) { - await this._lock.acquire() + this._lock.release() + } + try { + await onBlock(nextBlock, reorg) + } finally { + if (releaseLockOnCallback === true) { + await this._lock.acquire() + // If lock was released check if reorg occured + const nextBlockMayBeReorged = await this.getBlock(nextBlockNumber).catch( + (_e) => null + ) + reorgWhileOnBlock = nextBlockMayBeReorged + ? !equalsBytes(nextBlockMayBeReorged.hash(), nextBlock.hash()) + : true + } + } + + // if there was no reorg, update head + if (!reorgWhileOnBlock) { + this._heads[name] = nextBlock.hash() + lastBlock = nextBlock + nextBlockNumber++ + } + // Successful execution of onBlock, move the head pointer + blocksRanCounter++ + } catch (error: any) { + if (error.code === 'LEVEL_NOT_FOUND') { + break + } else { + throw error } - } - nextBlockNumber++ - blocksRanCounter++ - } catch (error: any) { - if (error.code === 'LEVEL_NOT_FOUND') { - break - } else { - throw error } } + return blocksRanCounter + } finally { + await this._saveHeads() } - - await this._saveHeads() - return blocksRanCounter }) } diff --git a/packages/client/lib/execution/vmexecution.ts b/packages/client/lib/execution/vmexecution.ts index 65aa39b1d7..c28b477324 100644 --- a/packages/client/lib/execution/vmexecution.ts +++ b/packages/client/lib/execution/vmexecution.ts @@ -34,7 +34,7 @@ export class VMExecution extends Execution { public receiptsManager?: ReceiptsManager private pendingReceipts?: Map - private vmPromise?: Promise + private vmPromise?: Promise /** Maximally tolerated block time before giving a warning on console */ private MAX_TOLERATED_BLOCK_TIME = 12 @@ -268,7 +268,7 @@ export class VMExecution extends Execution { async run(loop = true, runOnlybatched = false): Promise { if (this.running || !this.started || this.shutdown) return 0 this.running = true - let numExecuted: number | undefined + let numExecuted: number | null | undefined = undefined const { blockchain } = this.vm if (typeof blockchain.getIteratorHead !== 'function') { @@ -302,82 +302,105 @@ export class VMExecution extends Execution { headBlock = undefined parentState = undefined errorBlock = undefined - this.vmPromise = blockchain.iterator( - 'vm', - async (block: Block, reorg: boolean) => { - if (errorBlock !== undefined) return - // determine starting state for block run - // if we are just starting or if a chain reorg has happened - if (headBlock === undefined || reorg) { - const headBlock = await blockchain.getBlock(block.header.parentHash) - parentState = headBlock.header.stateRoot - - if (reorg) { - this.config.logger.info( - `Chain reorg happened, set new head to block number=${headBlock.header.number}, clearing state cache for VM execution.` - ) - } - } - // run block, update head if valid - try { - const { number, timestamp } = block.header - if (typeof blockchain.getTotalDifficulty !== 'function') { - throw new Error( - 'cannot get iterator head: blockchain has no getTotalDifficulty function' - ) + this.vmPromise = blockchain + .iterator( + 'vm', + async (block: Block, reorg: boolean) => { + // determine starting state for block run + // if we are just starting or if a chain reorg has happened + if (headBlock === undefined || reorg) { + const headBlock = await blockchain.getBlock(block.header.parentHash) + parentState = headBlock.header.stateRoot + + if (reorg) { + this.config.logger.info( + `Chain reorg happened, set new head to block number=${headBlock.header.number}, clearing state cache for VM execution.` + ) + } } - const td = await blockchain.getTotalDifficulty(block.header.parentHash) - const hardfork = this.config.execCommon.getHardforkByBlockNumber(number, td, timestamp) - if (hardfork !== this.hardfork) { - const hash = short(block.hash()) - this.config.logger.info( - `Execution hardfork switch on block number=${number} hash=${hash} old=${this.hardfork} new=${hardfork}` - ) - this.hardfork = this.config.execCommon.setHardforkByBlockNumber(number, td, timestamp) - } - let skipBlockValidation = false - if (this.config.execCommon.consensusType() === ConsensusType.ProofOfAuthority) { - // Block validation is redundant here and leads to consistency problems - // on PoA clique along blockchain-including validation checks - // (signer states might have moved on when sync is ahead) - skipBlockValidation = true - } + // run block, update head if valid + try { + const { number, timestamp } = block.header + if (typeof blockchain.getTotalDifficulty !== 'function') { + throw new Error( + 'cannot get iterator head: blockchain has no getTotalDifficulty function' + ) + } + const td = await blockchain.getTotalDifficulty(block.header.parentHash) - await this.runWithLock(async () => { - // we are skipping header validation because the block has been picked from the - // blockchain and header should have already been validated while putBlock - if (!this.started) { - throw Error('Execution stopped') + const hardfork = this.config.execCommon.getHardforkByBlockNumber( + number, + td, + timestamp + ) + if (hardfork !== this.hardfork) { + const hash = short(block.hash()) + this.config.logger.info( + `Execution hardfork switch on block number=${number} hash=${hash} old=${this.hardfork} new=${hardfork}` + ) + this.hardfork = this.config.execCommon.setHardforkByBlockNumber( + number, + td, + timestamp + ) } - const beforeTS = Date.now() - this.stats(this.vm) - const result = await this.vm.runBlock({ - block, - root: parentState, - clearCache: reorg ? true : false, - skipBlockValidation, - skipHeaderValidation: true, - }) - const afterTS = Date.now() - const diffSec = Math.round((afterTS - beforeTS) / 1000) - - if (diffSec > this.MAX_TOLERATED_BLOCK_TIME) { - const msg = `Slow block execution for block num=${ - block.header.number - } hash=0x${bytesToHex(block.hash())} txs=${block.transactions.length} gasUsed=${ - result.gasUsed - } time=${diffSec}secs` - this.config.logger.warn(msg) + let skipBlockValidation = false + if (this.config.execCommon.consensusType() === ConsensusType.ProofOfAuthority) { + // Block validation is redundant here and leads to consistency problems + // on PoA clique along blockchain-including validation checks + // (signer states might have moved on when sync is ahead) + skipBlockValidation = true } - void this.receiptsManager?.saveReceipts(block, result.receipts) - }) - txCounter += block.transactions.length - // set as new head block - headBlock = block - parentState = block.header.stateRoot - } catch (error: any) { + await this.runWithLock(async () => { + // we are skipping header validation because the block has been picked from the + // blockchain and header should have already been validated while putBlock + if (!this.started) { + throw Error('Execution stopped') + } + const beforeTS = Date.now() + this.stats(this.vm) + const result = await this.vm.runBlock({ + block, + root: parentState, + clearCache: reorg ? true : false, + skipBlockValidation, + skipHeaderValidation: true, + }) + const afterTS = Date.now() + const diffSec = Math.round((afterTS - beforeTS) / 1000) + + if (diffSec > this.MAX_TOLERATED_BLOCK_TIME) { + const msg = `Slow block execution for block num=${ + block.header.number + } hash=0x${bytesToHex(block.hash())} txs=${block.transactions.length} gasUsed=${ + result.gasUsed + } time=${diffSec}secs` + this.config.logger.warn(msg) + } + + void this.receiptsManager?.saveReceipts(block, result.receipts) + }) + + txCounter += block.transactions.length + // set as new head block + headBlock = block + parentState = block.header.stateRoot + } catch (error: any) { + // Store error block and throw which will make iterator stop, exit and save + // last successfully executed head as vmHead + errorBlock = block + throw error + } + }, + this.config.numBlocksPerIteration, + // release lock on this callback so other blockchain ops can happen while this block is being executed + true + ) + // Ensure to catch and not throw as this would lead to unCaughtException with process exit + .catch(async (error) => { + if (errorBlock !== undefined) { // TODO: determine if there is a way to differentiate between the cases // a) a bad block is served by a bad peer -> delete the block and restart sync // sync from parent block @@ -411,71 +434,65 @@ export class VMExecution extends Execution { }*/ // Option a): set iterator head to the parent block so that an // error can repeatedly processed for debugging - const { number } = block.header - const hash = short(block.hash()) + const { number } = errorBlock.header + const hash = short(errorBlock.hash()) this.config.logger.warn( `Execution of block number=${number} hash=${hash} hardfork=${this.hardfork} failed:\n${error}` ) if (this.config.debugCode) { - await debugCodeReplayBlock(this, block) + await debugCodeReplayBlock(this, errorBlock) } this.config.events.emit(Event.SYNC_EXECUTION_VM_ERROR, error) - errorBlock = block + const actualExecuted = Number(errorBlock.header.number - startHeadBlock.header.number) + return actualExecuted + } else { + this.config.logger.error(`VM execution failed with error`, error) + return null } - }, - this.config.numBlocksPerIteration, - // release lock on this callback so other blockchain ops can happen while this block is being executed - true - ) - numExecuted = await this.vmPromise + }) - // TODO: one should update the iterator head later as this is dangerous for the blockchain and can cause - // problems in concurrent execution - if (errorBlock !== undefined) { - await this.chain.blockchain.setIteratorHead( - 'vm', - (errorBlock as unknown as Block).header.parentHash - ) - return 0 - } - let endHeadBlock - if (typeof this.vm.blockchain.getIteratorHead === 'function') { - endHeadBlock = await this.vm.blockchain.getIteratorHead('vm') - } else { - throw new Error('cannot get iterator head: blockchain has no getIteratorHead function') - } + numExecuted = await this.vmPromise + if (numExecuted !== null) { + let endHeadBlock + if (typeof this.vm.blockchain.getIteratorHead === 'function') { + endHeadBlock = await this.vm.blockchain.getIteratorHead('vm') + } else { + throw new Error('cannot get iterator head: blockchain has no getIteratorHead function') + } - if (typeof numExecuted === 'number' && numExecuted > 0) { - const firstNumber = startHeadBlock.header.number - const firstHash = short(startHeadBlock.hash()) - const lastNumber = endHeadBlock.header.number - const lastHash = short(endHeadBlock.hash()) - const baseFeeAdd = - this.config.execCommon.gteHardfork(Hardfork.London) === true - ? `baseFee=${endHeadBlock.header.baseFeePerGas} ` - : '' - const tdAdd = - this.config.execCommon.gteHardfork(Hardfork.Paris) === true - ? '' - : `td=${this.chain.blocks.td} ` - this.config.logger.info( - `Executed blocks count=${numExecuted} first=${firstNumber} hash=${firstHash} ${tdAdd}${baseFeeAdd}hardfork=${this.hardfork} last=${lastNumber} hash=${lastHash} txs=${txCounter}` - ) - } else { - this.config.logger.debug( - `No blocks executed past chain head hash=${short(endHeadBlock.hash())} number=${ - endHeadBlock.header.number - }` - ) - } - startHeadBlock = endHeadBlock - if (typeof this.vm.blockchain.getCanonicalHeadBlock !== 'function') { - throw new Error( - 'cannot get iterator head: blockchain has no getCanonicalHeadBlock function' - ) + if (typeof numExecuted === 'number' && numExecuted > 0) { + const firstNumber = startHeadBlock.header.number + const firstHash = short(startHeadBlock.hash()) + const lastNumber = endHeadBlock.header.number + const lastHash = short(endHeadBlock.hash()) + const baseFeeAdd = + this.config.execCommon.gteHardfork(Hardfork.London) === true + ? `baseFee=${endHeadBlock.header.baseFeePerGas} ` + : '' + const tdAdd = + this.config.execCommon.gteHardfork(Hardfork.Paris) === true + ? '' + : `td=${this.chain.blocks.td} ` + this.config.logger.info( + `Executed blocks count=${numExecuted} first=${firstNumber} hash=${firstHash} ${tdAdd}${baseFeeAdd}hardfork=${this.hardfork} last=${lastNumber} hash=${lastHash} txs=${txCounter}` + ) + } else { + this.config.logger.debug( + `No blocks executed past chain head hash=${short(endHeadBlock.hash())} number=${ + endHeadBlock.header.number + }` + ) + } + startHeadBlock = endHeadBlock + if (typeof this.vm.blockchain.getCanonicalHeadBlock !== 'function') { + throw new Error( + 'cannot get iterator head: blockchain has no getCanonicalHeadBlock function' + ) + } + canonicalHead = await this.vm.blockchain.getCanonicalHeadBlock() } - canonicalHead = await this.vm.blockchain.getCanonicalHeadBlock() } + this.running = false return numExecuted ?? 0 } diff --git a/packages/client/lib/util/debug.ts b/packages/client/lib/util/debug.ts index 00d9702ed3..c072b0b020 100644 --- a/packages/client/lib/util/debug.ts +++ b/packages/client/lib/util/debug.ts @@ -6,7 +6,7 @@ import type { VMExecution } from '../execution' import type { Block } from '@ethereumjs/block' /** - * Generates a code snippet which can be used to replay an erraneous block + * Generates a code snippet which can be used to replay an erroneous block * locally in the VM * * @param block From 4f959676717e4061c70ae9ba9adb443c1116fc36 Mon Sep 17 00:00:00 2001 From: Holger Drewes Date: Fri, 5 May 2023 22:48:06 +0200 Subject: [PATCH 32/53] Client Memory Work / LRU Cache Updates (#2678) * Client: adjust frequency of cache stats output (lower frequency) * Client: move memory stats from execution to service module (to be execution-independent) * Client: add emergency shutdown on high memory load * Client/devp2p: fix number exceeds 53 bits error message * Client: add separate JS and TS client:start commands in package.json (default: build + JS) * devp2p: update lru-cache version, maxAge to ttl setting * Lint fixes * Trie/Blockchain: update lru-cache versions from v5 to v7, removed some unused @types/lru-cache references * Monorepo: update minimal Node.js version in engines field in package.json files from 14 to 16 * devp2p: substantially reduce DPT ping timeout from 10s to 2s (still far away from the real numbers) to better use the requests cache * Client: fix RlpxPeer memory leak * devp2p: small optimization * fix the script startup in sim runs * restore deleted hook * clear interval on close --------- Co-authored-by: harkamal Co-authored-by: acolytec3 <17355484+acolytec3@users.noreply.github.com> --- package-lock.json | 69 ++++--------------- packages/block/package.json | 3 +- packages/blockchain/package.json | 7 +- packages/blockchain/src/db/cache.ts | 7 +- packages/client/lib/config.ts | 6 ++ packages/client/lib/execution/execution.ts | 7 -- packages/client/lib/execution/vmexecution.ts | 23 ++----- packages/client/lib/net/server/rlpxserver.ts | 5 +- .../client/lib/service/ethereumservice.ts | 45 ++++++++++++ packages/client/package.json | 6 +- packages/client/test/sim/single-run.sh | 2 +- .../devp2p/examples/peer-communication.ts | 8 ++- packages/devp2p/package.json | 5 +- packages/devp2p/src/dpt/ban-list.ts | 10 +-- packages/devp2p/src/dpt/server.ts | 8 ++- packages/devp2p/src/protocol/eth.ts | 2 +- packages/devp2p/src/rlpx/rlpx.ts | 12 ++-- packages/ethash/package.json | 2 +- packages/evm/package.json | 3 +- packages/rlp/package.json | 2 +- packages/trie/package.json | 4 +- packages/tx/package.json | 2 +- packages/util/package.json | 2 +- packages/vm/package.json | 3 +- 24 files changed, 122 insertions(+), 121 deletions(-) diff --git a/package-lock.json b/package-lock.json index 2066aea123..6d015a9a9b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3278,10 +3278,6 @@ "version": "4.0.2", "license": "MIT" }, - "node_modules/@types/lru-cache": { - "version": "5.1.1", - "license": "MIT" - }, "node_modules/@types/minimatch": { "version": "3.0.5", "license": "MIT" @@ -11807,10 +11803,11 @@ "license": "MIT" }, "node_modules/lru-cache": { - "version": "5.1.1", - "license": "ISC", - "dependencies": { - "yallist": "^3.0.2" + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "engines": { + "node": ">=12" } }, "node_modules/ltgt": { @@ -17747,10 +17744,6 @@ "node": ">=10" } }, - "node_modules/yallist": { - "version": "3.1.1", - "license": "ISC" - }, "node_modules/yaml": { "version": "2.1.3", "dev": true, @@ -17841,7 +17834,6 @@ "ethereum-cryptography": "^1.1.2" }, "devDependencies": { - "@types/lru-cache": "^5.1.0", "c-kzg": "^2.0.4", "testdouble": "^3.17.2" }, @@ -17865,13 +17857,12 @@ "debug": "^4.3.3", "ethereum-cryptography": "^1.1.2", "level": "^8.0.0", - "lru-cache": "^5.1.1", + "lru-cache": "^7.18.3", "memory-level": "^1.0.0" }, "devDependencies": { "@types/async": "^2.4.1", - "@types/level-errors": "^3.0.0", - "@types/lru-cache": "^5.1.0" + "@types/level-errors": "^3.0.0" }, "engines": { "node": ">=14" @@ -18032,11 +18023,10 @@ "@ethereumjs/util": "^8.0.5", "@scure/base": "1.1.1", "@types/k-bucket": "^5.0.0", - "@types/lru-cache": "^5.1.0", "debug": "^4.3.3", "ethereum-cryptography": "^1.1.2", "k-bucket": "^5.0.0", - "lru-cache": "^5.1.1", + "lru-cache": "^7.18.3", "ms": "^0.7.1", "multiaddr": "^10.0.1", "scanf": "^1.1.2", @@ -18148,7 +18138,6 @@ "@ethereumjs/statemanager": "^1.0.4", "@types/benchmark": "^1.0.33", "@types/core-js": "^2.5.0", - "@types/lru-cache": "^5.1.0", "@types/minimist": "^1.2.2", "@types/node-dir": "^0.0.34", "benchmark": "^2.1.4", @@ -18209,14 +18198,6 @@ "typescript": "^4.4.2" } }, - "packages/statemanager/node_modules/lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "engines": { - "node": ">=12" - } - }, "packages/trie": { "name": "@ethereumjs/trie", "version": "5.0.4", @@ -18226,7 +18207,7 @@ "@ethereumjs/util": "^8.0.5", "@types/readable-stream": "^2.3.13", "ethereum-cryptography": "^1.1.2", - "lru-cache": "^5.1.1", + "lru-cache": "^7.18.3", "readable-stream": "^3.6.0" }, "devDependencies": { @@ -18335,7 +18316,6 @@ "@ethersproject/abi": "^5.0.12", "@types/benchmark": "^1.0.33", "@types/core-js": "^2.5.0", - "@types/lru-cache": "^5.1.0", "@types/minimist": "^1.2.2", "@types/node-dir": "^0.0.34", "benchmark": "^2.1.4", @@ -19572,7 +19552,6 @@ "@ethereumjs/trie": "^5.0.4", "@ethereumjs/tx": "^4.1.1", "@ethereumjs/util": "^8.0.5", - "@types/lru-cache": "^5.1.0", "c-kzg": "^2.0.4", "ethereum-cryptography": "^1.1.2", "testdouble": "^3.17.2" @@ -19590,12 +19569,11 @@ "@ethereumjs/util": "^8.0.5", "@types/async": "^2.4.1", "@types/level-errors": "^3.0.0", - "@types/lru-cache": "^5.1.0", "abstract-level": "^1.0.3", "debug": "^4.3.3", "ethereum-cryptography": "^1.1.2", "level": "^8.0.0", - "lru-cache": "^5.1.1", + "lru-cache": "^7.18.3", "memory-level": "^1.0.0" } }, @@ -19726,13 +19704,12 @@ "@types/debug": "^4.1.4", "@types/ip": "^1.1.0", "@types/k-bucket": "^5.0.0", - "@types/lru-cache": "^5.1.0", "@types/ms": "^0.7.30", "chalk": "^2.4.2", "debug": "^4.3.3", "ethereum-cryptography": "^1.1.2", "k-bucket": "^5.0.0", - "lru-cache": "^5.1.1", + "lru-cache": "^7.18.3", "ms": "^0.7.1", "multiaddr": "^10.0.1", "scanf": "^1.1.2", @@ -19801,7 +19778,6 @@ "@ethereumjs/util": "^8.0.5", "@types/benchmark": "^1.0.33", "@types/core-js": "^2.5.0", - "@types/lru-cache": "^5.1.0", "@types/minimist": "^1.2.2", "@types/node-dir": "^0.0.34", "benchmark": "^2.1.4", @@ -19847,13 +19823,6 @@ "tape": "^5.3.1", "ts-node": "^10.2.1", "typescript": "^4.4.2" - }, - "dependencies": { - "lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==" - } } }, "@ethereumjs/trie": { @@ -19871,7 +19840,7 @@ "level-mem": "^6.0.1", "levelup": "^5.1.1", "lmdb": "^2.5.3", - "lru-cache": "^5.1.1", + "lru-cache": "^7.18.3", "memory-level": "^1.0.0", "micro-bmark": "0.2.0", "readable-stream": "^3.6.0" @@ -19927,7 +19896,6 @@ "@ethersproject/abi": "^5.0.12", "@types/benchmark": "^1.0.33", "@types/core-js": "^2.5.0", - "@types/lru-cache": "^5.1.0", "@types/minimist": "^1.2.2", "@types/node-dir": "^0.0.34", "benchmark": "^2.1.4", @@ -20816,9 +20784,6 @@ "@types/long": { "version": "4.0.2" }, - "@types/lru-cache": { - "version": "5.1.1" - }, "@types/minimatch": { "version": "3.0.5" }, @@ -26719,10 +26684,9 @@ "dev": true }, "lru-cache": { - "version": "5.1.1", - "requires": { - "yallist": "^3.0.2" - } + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==" }, "ltgt": { "version": "2.2.1", @@ -30675,9 +30639,6 @@ "y18n": { "version": "5.0.8" }, - "yallist": { - "version": "3.1.1" - }, "yaml": { "version": "2.1.3", "dev": true diff --git a/packages/block/package.json b/packages/block/package.json index fbd77226a8..373eac03d1 100644 --- a/packages/block/package.json +++ b/packages/block/package.json @@ -46,11 +46,10 @@ "ethereum-cryptography": "^1.1.2" }, "devDependencies": { - "@types/lru-cache": "^5.1.0", "c-kzg": "^2.0.4", "testdouble": "^3.17.2" }, "engines": { - "node": ">=14" + "node": ">=16" } } diff --git a/packages/blockchain/package.json b/packages/blockchain/package.json index a92383cca3..7745f1a4a8 100644 --- a/packages/blockchain/package.json +++ b/packages/blockchain/package.json @@ -49,15 +49,14 @@ "debug": "^4.3.3", "ethereum-cryptography": "^1.1.2", "level": "^8.0.0", - "lru-cache": "^5.1.1", + "lru-cache": "^7.18.3", "memory-level": "^1.0.0" }, "devDependencies": { "@types/async": "^2.4.1", - "@types/level-errors": "^3.0.0", - "@types/lru-cache": "^5.1.0" + "@types/level-errors": "^3.0.0" }, "engines": { - "node": ">=14" + "node": ">=16" } } diff --git a/packages/blockchain/src/db/cache.ts b/packages/blockchain/src/db/cache.ts index 9df9511420..c7d82c7c94 100644 --- a/packages/blockchain/src/db/cache.ts +++ b/packages/blockchain/src/db/cache.ts @@ -1,5 +1,8 @@ import { bytesToHex } from 'ethereum-cryptography/utils' -import * as LRUCache from 'lru-cache' + +import type LRUCache from 'lru-cache' + +const LRU = require('lru-cache') /** * Simple LRU Cache that allows for keys of type Uint8Array @@ -9,7 +12,7 @@ export class Cache { _cache: LRUCache constructor(opts: LRUCache.Options) { - this._cache = new LRUCache(opts) + this._cache = new LRU(opts) } set(key: string | Uint8Array, value: V): void { diff --git a/packages/client/lib/config.ts b/packages/client/lib/config.ts index 6ca51d207a..c184d492fb 100644 --- a/packages/client/lib/config.ts +++ b/packages/client/lib/config.ts @@ -382,6 +382,8 @@ export class Config { public lastSyncDate: number /** Best known block height */ public syncTargetHeight?: bigint + /** Client is in the process of shutting down */ + public shutdown: boolean = false public readonly chainCommon: Common public readonly execCommon: Common @@ -472,6 +474,10 @@ export class Config { } }) } + + this.events.once(Event.CLIENT_SHUTDOWN, () => { + this.shutdown = true + }) } /** diff --git a/packages/client/lib/execution/execution.ts b/packages/client/lib/execution/execution.ts index 0fe0c264b3..c0c43c1ddd 100644 --- a/packages/client/lib/execution/execution.ts +++ b/packages/client/lib/execution/execution.ts @@ -1,5 +1,3 @@ -import { Event } from '../types' - import type { Chain } from '../blockchain' import type { Config } from '../config' import type { AbstractLevel } from 'abstract-level' @@ -27,7 +25,6 @@ export abstract class Execution { public running: boolean = false public started: boolean = false - public shutdown: boolean = false /** * Create new execution module @@ -38,10 +35,6 @@ export abstract class Execution { this.chain = options.chain this.stateDB = options.stateDB this.metaDB = options.metaDB - - this.config.events.once(Event.CLIENT_SHUTDOWN, () => { - this.shutdown = true - }) } /** diff --git a/packages/client/lib/execution/vmexecution.ts b/packages/client/lib/execution/vmexecution.ts index c28b477324..6036721dd3 100644 --- a/packages/client/lib/execution/vmexecution.ts +++ b/packages/client/lib/execution/vmexecution.ts @@ -12,22 +12,19 @@ import { Lock, bytesToHex, bytesToPrefixedHexString, equalsBytes } from '@ethere import { VM } from '@ethereumjs/vm' import { Event } from '../types' -import { getV8Engine, short } from '../util' +import { short } from '../util' import { debugCodeReplayBlock } from '../util/debug' import { Execution } from './execution' import { LevelDB } from './level' import { ReceiptsManager } from './receipt' -import type { V8Engine } from '../util' import type { ExecutionOptions } from './execution' import type { Block } from '@ethereumjs/block' import type { RunBlockOpts, TxReceipt } from '@ethereumjs/vm' export class VMExecution extends Execution { private _lock = new Lock() - // A handle to v8Engine lib for mem stats, assigned on open if running in node - private v8Engine: V8Engine | null = null public vm: VM public hardfork: string = '' @@ -42,7 +39,7 @@ export class VMExecution extends Execution { /** * Display state cache stats every num blocks */ - private STATS_NUM_BLOCKS = 500 + private STATS_NUM_BLOCKS = 1000 private statsCount = 0 /** @@ -122,10 +119,6 @@ export class VMExecution extends Execution { return } - if (this.v8Engine === null) { - this.v8Engine = await getV8Engine() - } - await this.vm.init() if (typeof this.vm.blockchain.getIteratorHead !== 'function') { throw new Error('cannot get iterator head: blockchain has no getIteratorHead function') @@ -266,7 +259,7 @@ export class VMExecution extends Execution { * @returns number of blocks executed */ async run(loop = true, runOnlybatched = false): Promise { - if (this.running || !this.started || this.shutdown) return 0 + if (this.running || !this.started || this.config.shutdown) return 0 this.running = true let numExecuted: number | null | undefined = undefined @@ -290,7 +283,7 @@ export class VMExecution extends Execution { while ( this.started && - !this.shutdown && + !this.config.shutdown && (!runOnlybatched || (runOnlybatched && canonicalHead.header.number - startHeadBlock.header.number >= @@ -642,14 +635,6 @@ export class VMExecution extends Execution { `Trie cache stats size=${tStats.size} reads=${tStats.cache.reads} hits=${tStats.cache.hits} ` + `writes=${tStats.cache.writes} readsDB=${tStats.db.reads} hitsDB=${tStats.db.hits} writesDB=${tStats.db.writes}` ) - - if (this.v8Engine !== null) { - const { used_heap_size, heap_size_limit } = this.v8Engine.getHeapStatistics() - - const heapUsed = Math.round(used_heap_size / 1000 / 1000) // MB - const percentage = Math.round((100 * used_heap_size) / heap_size_limit) - this.config.logger.info(`Memory stats usage=${heapUsed} MB percentage=${percentage}%`) - } this.statsCount = 0 } } diff --git a/packages/client/lib/net/server/rlpxserver.ts b/packages/client/lib/net/server/rlpxserver.ts index 7180f2e0d8..4f7026ab9e 100644 --- a/packages/client/lib/net/server/rlpxserver.ts +++ b/packages/client/lib/net/server/rlpxserver.ts @@ -250,7 +250,7 @@ export class RlpxServer extends Server { }) this.rlpx.on('peer:added', async (rlpxPeer: Devp2pRLPxPeer) => { - const peer = new RlpxPeer({ + let peer: RlpxPeer | null = new RlpxPeer({ config: this.config, id: bytesToHex(rlpxPeer.getId()!), host: rlpxPeer._socket.remoteAddress!, @@ -266,6 +266,9 @@ export class RlpxServer extends Server { this.config.logger.debug(`Peer connected: ${peer}`) this.config.events.emit(Event.PEER_CONNECTED, peer) } catch (error: any) { + // Fixes a memory leak where RlpxPeer objects could not be GCed, + // likely to the complex two-way bound-protocol logic + peer = null this.error(error) } }) diff --git a/packages/client/lib/service/ethereumservice.ts b/packages/client/lib/service/ethereumservice.ts index 0bac4c841b..450fe8e3e3 100644 --- a/packages/client/lib/service/ethereumservice.ts +++ b/packages/client/lib/service/ethereumservice.ts @@ -1,9 +1,11 @@ import { Chain } from '../blockchain' import { FlowControl } from '../net/protocol/flowcontrol' +import { getV8Engine } from '../util' import { Service } from './service' import type { Synchronizer } from '../sync' +import type { V8Engine } from '../util' import type { ServiceOptions } from './service' import type { AbstractLevel } from 'abstract-level' @@ -38,6 +40,22 @@ export class EthereumService extends Service { public timeout: number public synchronizer?: Synchronizer + // A handle to v8Engine lib for mem stats, assigned on open if running in node + private v8Engine: V8Engine | null = null + + /** + * Interval for client stats output (e.g. memory) (in ms) + */ + private STATS_INTERVAL = 30000 + + /** + * Shutdown the client when memory threshold is reached (in percent) + * + */ + private MEMORY_SHUTDOWN_THRESHOLD = 95 + + private _statsInterval: NodeJS.Timeout | undefined /* global NodeJS */ + /** * Create new ETH service */ @@ -80,9 +98,35 @@ export class EthereumService extends Service { } await super.start() void this.synchronizer?.start() + + if (this.v8Engine === null) { + this.v8Engine = await getV8Engine() + } + + this._statsInterval = setInterval( + // eslint-disable-next-line @typescript-eslint/await-thenable + await this.stats.bind(this), + this.STATS_INTERVAL + ) + return true } + stats() { + if (this.v8Engine !== null) { + const { used_heap_size, heap_size_limit } = this.v8Engine.getHeapStatistics() + + const heapUsed = Math.round(used_heap_size / 1000 / 1000) // MB + const percentage = Math.round((100 * used_heap_size) / heap_size_limit) + this.config.logger.info(`Memory stats usage=${heapUsed} MB percentage=${percentage}%`) + + if (percentage >= this.MEMORY_SHUTDOWN_THRESHOLD && !this.config.shutdown) { + this.config.logger.error('EMERGENCY SHUTDOWN DUE TO HIGH MEMORY LOAD...') + process.kill(process.pid, 'SIGINT') + } + } + } + /** * Stop service. Interrupts blockchain synchronization if in progress. */ @@ -90,6 +134,7 @@ export class EthereumService extends Service { if (!this.running) { return false } + clearInterval(this._statsInterval) await this.synchronizer?.stop() await super.stop() return true diff --git a/packages/client/package.json b/packages/client/package.json index 21d848c671..174248e1b5 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -36,7 +36,9 @@ "build:common": "../../config/cli/ts-build.sh", "bundle": "webpack", "clean": "../../config/cli/clean-package.sh", - "client:start": "ts-node bin/cli.ts", + "client:start:ts": "ts-node bin/cli.ts", + "client:start:js": "npm run build && node dist/bin/cli.js", + "client:start": "npm run client:start:js --", "client:start:dev1": "npm run client:start -- --discDns=false --discV4=false --bootnodes", "client:start:dev2": "npm run client:start -- --discDns=false --discV4=false --port=30304 --dataDir=datadir-dev2", "coverage": "c8 --all --reporter=lcov --reporter=text npm run test:unit", @@ -120,7 +122,7 @@ "webpack-cli": "^4.8.0" }, "engines": { - "node": ">=14" + "node": ">=16" }, "devDependenciesComments": { "node-fetch": "Hotfix for client browser build error in older Node versions (12/14), #1305, 2021-06-18" diff --git a/packages/client/test/sim/single-run.sh b/packages/client/test/sim/single-run.sh index 0222cb298f..f233be3482 100755 --- a/packages/client/test/sim/single-run.sh +++ b/packages/client/test/sim/single-run.sh @@ -195,7 +195,7 @@ if [ "$MULTIPEER" == "peer1" ] then case $ELCLIENT in ethereumjs) - ejsCmd="npm run client:start -- --dataDir $DATADIR/ethereumjs --gethGenesis $scriptDir/configs/$NETWORK.json --rpc --rpcEngine --rpcEngineAuth false $EL_PORT_ARGS" + ejsCmd="npm run client:start:ts -- --dataDir $DATADIR/ethereumjs --gethGenesis $scriptDir/configs/$NETWORK.json --rpc --rpcEngine --rpcEngineAuth false $EL_PORT_ARGS" ;; geth) # geth will be mounted in docker with DATADIR to /data diff --git a/packages/devp2p/examples/peer-communication.ts b/packages/devp2p/examples/peer-communication.ts index f71f3ce0c2..b61a418de7 100644 --- a/packages/devp2p/examples/peer-communication.ts +++ b/packages/devp2p/examples/peer-communication.ts @@ -4,7 +4,9 @@ import { Chain, Common, Hardfork } from '@ethereumjs/common' import { RLP } from '@ethereumjs/rlp' import { TransactionFactory, TypedTransaction } from '@ethereumjs/tx' import chalk from 'chalk' -import * as LRUCache from 'lru-cache' +import type LRUCache from 'lru-cache' + +const LRU = require('lru-cache') import ms = require('ms') import * as devp2p from '../src/index' @@ -328,7 +330,7 @@ dpt.addPeer({ address: '127.0.0.1', udpPort: 30303, tcpPort: 30303 }) .catch((err) => console.log(`error on connection to local node: ${err.stack ?? err}`)) */ -const txCache = new LRUCache({ max: 1000 }) +const txCache: LRUCache = new LRU({ max: 1000 }) function onNewTx(tx: TypedTransaction, peer: Peer) { const txHashHex = bytesToHex(tx.hash()) if (txCache.has(txHashHex)) return @@ -337,7 +339,7 @@ function onNewTx(tx: TypedTransaction, peer: Peer) { console.log(`New tx: ${txHashHex} (from ${getPeerAddr(peer)})`) } -const blocksCache = new LRUCache({ max: 100 }) +const blocksCache: LRUCache = new LRU({ max: 100 }) function onNewBlock(block: Block, peer: Peer) { const blockHashHex = bytesToHex(block.hash()) const blockNumber = block.header.number diff --git a/packages/devp2p/package.json b/packages/devp2p/package.json index 72befc7883..7896a615eb 100644 --- a/packages/devp2p/package.json +++ b/packages/devp2p/package.json @@ -54,11 +54,10 @@ "@ethereumjs/util": "^8.0.5", "@scure/base": "1.1.1", "@types/k-bucket": "^5.0.0", - "@types/lru-cache": "^5.1.0", "debug": "^4.3.3", "ethereum-cryptography": "^1.1.2", "k-bucket": "^5.0.0", - "lru-cache": "^5.1.1", + "lru-cache": "^7.18.3", "ms": "^0.7.1", "multiaddr": "^10.0.1", "scanf": "^1.1.2", @@ -75,6 +74,6 @@ "testdouble": "^3.8.2" }, "engines": { - "node": ">=14" + "node": ">=16" } } diff --git a/packages/devp2p/src/dpt/ban-list.ts b/packages/devp2p/src/dpt/ban-list.ts index fe130f50d8..4c509182c5 100644 --- a/packages/devp2p/src/dpt/ban-list.ts +++ b/packages/devp2p/src/dpt/ban-list.ts @@ -1,11 +1,13 @@ import { debug as createDebugLogger } from 'debug' -import * as LRUCache from 'lru-cache' import { formatLogId } from '../util' import { KBucket } from './kbucket' import type { PeerInfo } from './dpt' +import type LRUCache from 'lru-cache' + +const LRU = require('lru-cache') const debug = createDebugLogger('devp2p:dpt:ban-list') const verbose = createDebugLogger('verbose').enabled @@ -13,13 +15,13 @@ const verbose = createDebugLogger('verbose').enabled export class BanList { private lru: LRUCache constructor() { - this.lru = new LRUCache({ max: 30000 }) // 10k should be enough (each peer obj can has 3 keys) + this.lru = new LRU({ max: 10000 }) } add(obj: string | Uint8Array | PeerInfo, maxAge?: number) { for (const key of KBucket.getKeys(obj)) { - this.lru.set(key, true, maxAge) - debug(`Added peer ${formatLogId(key, verbose)}, size: ${this.lru.length}`) + this.lru.set(key, true, { ttl: maxAge }) + debug(`Added peer ${formatLogId(key, verbose)}, size: ${this.lru.size}`) } } diff --git a/packages/devp2p/src/dpt/server.ts b/packages/devp2p/src/dpt/server.ts index 8c70048fa2..9c60d8a5d1 100644 --- a/packages/devp2p/src/dpt/server.ts +++ b/packages/devp2p/src/dpt/server.ts @@ -2,7 +2,6 @@ import { debug as createDebugLogger } from 'debug' import * as dgram from 'dgram' import { bytesToHex } from 'ethereum-cryptography/utils' import { EventEmitter } from 'events' -import LRUCache = require('lru-cache') import ms = require('ms') import { createDeferred, devp2pDebug, formatLogId, pk2id } from '../util' @@ -12,6 +11,9 @@ import { decode, encode } from './message' import type { DPT, PeerInfo } from './dpt' import type { Debugger } from 'debug' import type { Socket as DgramSocket, RemoteInfo } from 'dgram' +import type LRUCache from 'lru-cache' + +const LRU = require('lru-cache') const DEBUG_BASE_NAME = 'dpt:server' const verbose = createDebugLogger('verbose').enabled @@ -57,10 +59,10 @@ export class Server extends EventEmitter { this._dpt = dpt this._privateKey = privateKey - this._timeout = options.timeout ?? ms('10s') + this._timeout = options.timeout ?? ms('2s') this._endpoint = options.endpoint ?? { address: '0.0.0.0', udpPort: null, tcpPort: null } this._requests = new Map() - this._requestsCache = new LRUCache({ max: 1000, maxAge: ms('1s'), stale: false }) + this._requestsCache = new LRU({ max: 1000, ttl: ms('1s'), stale: false }) const createSocket = options.createSocket ?? dgram.createSocket.bind(null, { type: 'udp4' }) this._socket = createSocket() diff --git a/packages/devp2p/src/protocol/eth.ts b/packages/devp2p/src/protocol/eth.ts index 74ffc3e8d5..56ecd5df8c 100644 --- a/packages/devp2p/src/protocol/eth.ts +++ b/packages/devp2p/src/protocol/eth.ts @@ -237,7 +237,7 @@ export class ETH extends Protocol { status[5] !== undefined ? bytesToPrefixedHexString(status[5][0] as Uint8Array) : '-' }` sStr += `, ForkNext: ${ - (status[5][1] as Uint8Array).length > 0 ? bytesToInt(status[5][1] as Uint8Array) : '-' + (status[5][1] as Uint8Array).length > 0 ? bytesToHex(status[5][1] as Uint8Array) : '-' }` } sStr += `]` diff --git a/packages/devp2p/src/rlpx/rlpx.ts b/packages/devp2p/src/rlpx/rlpx.ts index 030fdc75f1..f8152585ed 100644 --- a/packages/devp2p/src/rlpx/rlpx.ts +++ b/packages/devp2p/src/rlpx/rlpx.ts @@ -3,7 +3,6 @@ import { debug as createDebugLogger } from 'debug' import { getPublicKey } from 'ethereum-cryptography/secp256k1' import { bytesToHex, equalsBytes, hexToBytes, utf8ToBytes } from 'ethereum-cryptography/utils' import { EventEmitter } from 'events' -import * as LRUCache from 'lru-cache' import ms = require('ms') import * as net from 'net' import * as os from 'os' @@ -16,6 +15,9 @@ import type { DPT, PeerInfo } from '../dpt' import type { Capabilities } from './peer' import type { Common } from '@ethereumjs/common' import type { Debugger } from 'debug' +import type LRUCache from 'lru-cache' + +const LRU = require('lru-cache') // note: relative path only valid in .js file in dist const { version: pVersion } = require('../../package.json') @@ -85,9 +87,9 @@ export class RLPx extends EventEmitter { this._debug(`banning peer with missing tcp port: ${peer.address}`) return } - - if (this._peersLRU.has(bytesToHex(peer.id!))) return - this._peersLRU.set(bytesToHex(peer.id!), true) + const key = bytesToHex(peer.id!) + if (this._peersLRU.has(key)) return + this._peersLRU.set(key, true) if (this._getOpenSlots() > 0) { return this._connectToPeer(peer) @@ -115,7 +117,7 @@ export class RLPx extends EventEmitter { : devp2pDebug.extend(DEBUG_BASE_NAME) this._peers = new Map() this._peersQueue = [] - this._peersLRU = new LRUCache({ max: 25000 }) + this._peersLRU = new LRU({ max: 25000 }) const REFILL_INTERVALL = ms('10s') const refillIntervalSubdivided = Math.floor(REFILL_INTERVALL / 10) this._refillIntervalId = setInterval(() => this._refillConnections(), refillIntervalSubdivided) diff --git a/packages/ethash/package.json b/packages/ethash/package.json index 17f11016b3..2756032064 100644 --- a/packages/ethash/package.json +++ b/packages/ethash/package.json @@ -49,6 +49,6 @@ "memory-level": "^1.0.0" }, "engines": { - "node": ">=14" + "node": ">=16" } } diff --git a/packages/evm/package.json b/packages/evm/package.json index 8f670b925a..7152de7605 100644 --- a/packages/evm/package.json +++ b/packages/evm/package.json @@ -58,7 +58,6 @@ "@ethereumjs/statemanager": "^1.0.4", "@types/benchmark": "^1.0.33", "@types/core-js": "^2.5.0", - "@types/lru-cache": "^5.1.0", "@types/minimist": "^1.2.2", "@types/node-dir": "^0.0.34", "benchmark": "^2.1.4", @@ -70,6 +69,6 @@ "solc": "^0.8.1" }, "engines": { - "node": ">=14" + "node": ">=16" } } diff --git a/packages/rlp/package.json b/packages/rlp/package.json index 6302d6b84c..6b70eb3ab2 100644 --- a/packages/rlp/package.json +++ b/packages/rlp/package.json @@ -49,6 +49,6 @@ "tsc": "../../config/cli/ts-compile.sh" }, "engines": { - "node": ">=14" + "node": ">=16" } } diff --git a/packages/trie/package.json b/packages/trie/package.json index cd054e0c50..df48c8ebff 100644 --- a/packages/trie/package.json +++ b/packages/trie/package.json @@ -49,7 +49,7 @@ "@ethereumjs/util": "^8.0.5", "@types/readable-stream": "^2.3.13", "ethereum-cryptography": "^1.1.2", - "lru-cache": "^5.1.1", + "lru-cache": "^7.18.3", "readable-stream": "^3.6.0" }, "devDependencies": { @@ -65,6 +65,6 @@ "micro-bmark": "0.2.0" }, "engines": { - "node": ">=14" + "node": ">=16" } } diff --git a/packages/tx/package.json b/packages/tx/package.json index b8c4c502ad..a5219acd39 100644 --- a/packages/tx/package.json +++ b/packages/tx/package.json @@ -73,6 +73,6 @@ "testdouble": "^3.17.2" }, "engines": { - "node": ">=14" + "node": ">=16" } } diff --git a/packages/util/package.json b/packages/util/package.json index 86ca7292dd..c0eda02468 100644 --- a/packages/util/package.json +++ b/packages/util/package.json @@ -100,6 +100,6 @@ } }, "engines": { - "node": ">=14" + "node": ">=16" } } diff --git a/packages/vm/package.json b/packages/vm/package.json index 29c0c0f7d8..c03a914755 100644 --- a/packages/vm/package.json +++ b/packages/vm/package.json @@ -74,7 +74,6 @@ "@ethersproject/abi": "^5.0.12", "@types/benchmark": "^1.0.33", "@types/core-js": "^2.5.0", - "@types/lru-cache": "^5.1.0", "@types/minimist": "^1.2.2", "@types/node-dir": "^0.0.34", "benchmark": "^2.1.4", @@ -93,6 +92,6 @@ "typescript": "^4.4.2" }, "engines": { - "node": ">=14" + "node": ">=16" } } From 01d88bc1fb22d705540cba24b868250162a5f2aa Mon Sep 17 00:00:00 2001 From: g11tech Date: Mon, 8 May 2023 16:09:24 +0530 Subject: [PATCH 33/53] client: Add 4844 devnet5 blob post utility (#2674) * client: Add 4844 devnet5 blob post utility * fx * update error handling * lint * fix sharding spec * update image * add instructions * allow gas specification via env vars * undo tx lib change and cleanup --- packages/client/test/sim/4844-devnet-5.md | 17 +++ packages/client/test/sim/4844.md | 8 +- packages/client/test/sim/4844devnet5.spec.ts | 111 +++++++++++++++++++ packages/client/test/sim/sharding.spec.ts | 12 +- packages/client/test/sim/simutils.ts | 34 +++--- 5 files changed, 158 insertions(+), 24 deletions(-) create mode 100644 packages/client/test/sim/4844-devnet-5.md create mode 100644 packages/client/test/sim/4844devnet5.spec.ts diff --git a/packages/client/test/sim/4844-devnet-5.md b/packages/client/test/sim/4844-devnet-5.md new file mode 100644 index 0000000000..b48cedf802 --- /dev/null +++ b/packages/client/test/sim/4844-devnet-5.md @@ -0,0 +1,17 @@ +A blob tx gen utility for seeding devnet5 (or subsequent devnets/testnests with blobs) + +how to run: + +1. Clone the repo set to branch `develop-v7` and run `npm i` with nodejs `18` installed and latest npm version +2. Run the blob gen utility (replace PRIVATE_KEY with a funded account private key and RPC_URL with an authenticated rpc url): + ```typescript + cd packages/client + PRIVATE_KEY=ae557af4ceefda559c924516cabf029bedc36b68109bf8d6183fe96e04121f4e RPC_URL=https://rpc.lodestar-ethereumjs-1.srv.4844-devnet-5.ethpandaops.io npm run tape -- test/sim/4844devnet5.spec.ts + ``` + + It runs with current chainId of `4844001005`, if you want to override pass `CHAIN_ID=` env param in above command + currently it posts 2 txs, but that can be modified with another env variable `NUM_TXS` + + You can manipulate the fees for the txs using env variables in the following way (for e.g. to replace a low fee stuck tx): + + `GAS_LIMIT=0xffffff MAX_FEE=1000000000 MAX_PRIORITY=100000000 MAX_DATAFEE=100000000 RIVATE_KEY=ae557af4ceefda559c924516cabf029bedc36b68109bf8d6183fe96e04121f4e RPC_URL=https://rpc.lodestar-ethereumjs-1.srv.4844-devnet-5.ethpandaops.io npm run tape -- test/sim/4844devnet5.spec.ts` diff --git a/packages/client/test/sim/4844.md b/packages/client/test/sim/4844.md index 4b23249ac6..8758cfe2aa 100644 --- a/packages/client/test/sim/4844.md +++ b/packages/client/test/sim/4844.md @@ -5,10 +5,10 @@ Note: All commands should be run from the `client` package directory root (so so ## Running a local devnet 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` +`NETWORK=sharding EXTRA_CL_PARAMS="--params.CAPELLA_FORK_EPOCH 0 --params.DENEB_FORK_EPOCH 0" LODE_IMAGE=g11tech/lodestar:blobs-2467 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` +`MULTIPEER=syncpeer NETWORK=sharding EXTRA_CL_PARAMS="--params.CAPELLA_FORK_EPOCH 0 --params.DENEB_FORK_EPOCH 0" LODE_IMAGE=g11tech/lodestar:blobs-2467 DATADIR=path/to/your/data/directory test/sim/./single-run.sh` 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` @@ -25,10 +25,10 @@ You don't need to externally start the nodes, the sim tests will do all that for Run Step 1 & 3 together: -`LODE_IMAGE=g11tech/lodestar:decoupled DATADIR=path/to/your/data/directory npm run tape -- test/sim/sharding.spec.ts` +`LODE_IMAGE=g11tech/lodestar:blobs-2467 DATADIR=path/to/your/data/directory npm run tape -- test/sim/sharding.spec.ts` ### Run Step 1, 2 & 3 together -`WITH_PEER=syncpeer LODE_IMAGE=g11tech/lodestar:decoupled DATADIR=path/to/your/data/directory npm run tape -- test/sim/sharding.spec.ts` +`WITH_PEER=syncpeer LODE_IMAGE=g11tech/lodestar:blobs-2467 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/4844devnet5.spec.ts b/packages/client/test/sim/4844devnet5.spec.ts new file mode 100644 index 0000000000..b41d5bc53d --- /dev/null +++ b/packages/client/test/sim/4844devnet5.spec.ts @@ -0,0 +1,111 @@ +import { Common } from '@ethereumjs/common' +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, + runTxHelper, + startNetwork, + waitForELStart, +} from './simutils' + +const pkey = hexStringToBytes( + process.env.PRIVATE_KEY ?? 'ae557af4ceefda559c924516cabf029bedc36b68109bf8d6183fe96e04121f4e' +) +const sender = bytesToPrefixedHexString(privateToAddress(pkey)) +const rpcUrl = + process.env.RPC_URL ?? 'https://rpc.lodestar-ethereumjs-1.srv.4844-devnet-5.ethpandaops.io' +if (rpcUrl === undefined) { + throw Error('Need a valid RPC url to connect to EL client') +} + +const client = Client.https(rpcUrl as any) +// pick sharding spec which has cancun hf instantiated from genesis itself +// only override the chainid if provided +const chainId = Number(process.env.CHAIN_ID ?? 4844001005) +const numTxs = Number(process.env.NUM_TXS ?? 1) +console.log({ sender, rpcUrl, chainId, numTxs }) + +const network = 'sharding' +const shardingJson = require(`./configs/${network}.json`) + +// safely change chainId without modifying undelying json +const commonJson = { ...shardingJson } +commonJson.config = { ...commonJson.config, chainId } +const common = Common.fromGethGenesis(commonJson, { chain: network }) + +export async function runTx(data: string, to?: string, value?: bigint) { + return runTxHelper({ client, common, sender, pkey }, data, to, value) +} + +tape(`running txes on ${rpcUrl}`, async (t) => { + const { teardownCallBack, result } = await startNetwork(network, client, { + filterKeywords, + filterOutWords, + externalRun: 'true', + }) + t.pass(`connected to client ${result}`) + + console.log(`Checking for network running...`) + try { + await waitForELStart(client) + t.pass(`${result} confirmed running`) + } catch (e) { + t.fail(`failed to confirm ${result} running`) + throw e + } + + t.test('run blob transactions', async (st) => { + const nonceFetch = await client.request( + 'eth_getTransactionCount', + [sender.toString(), 'latest'], + 2.0 + ) + const nonce = Number(nonceFetch.result) + st.pass(`fetched ${sender}'s nonce=${nonce} for blob txs`) + + const txns = await createBlobTxs( + numTxs - 1, + 4096, + pkey, + nonce, + { + to: bytesToPrefixedHexString(randomBytes(20)), + chainId, + maxFeePerDataGas: BigInt(process.env.MAX_DATAFEE ?? 100000000n), + maxPriorityFeePerGas: BigInt(process.env.MAX_PRIORITY ?? 100000000n), + maxFeePerGas: BigInt(process.env.MAX_FEE ?? 1000000000n), + gasLimit: BigInt(process.env.GAS_LIMIT ?? 0xffffffn), + }, + { common } + ) + const txHashes = [] + for (const txn of txns) { + const res = await client.request('eth_sendRawTransaction', [txn], 2.0) + if (res.result === undefined) { + console.log('eth_sendRawTransaction returned invalid response', res) + st.fail(`Unable to post all txs`) + break + } + st.pass(`posted tx with hash=${res.result}`) + txHashes.push(res.result) + } + st.pass(`posted txs=${txHashes.length}`) + }) + + t.test('cleanup', async (st) => { + try { + await teardownCallBack() + st.pass('script terminated') + } catch (e) { + st.fail('could not terminate properly') + } + st.end() + }) + + t.end() +}) diff --git a/packages/client/test/sim/sharding.spec.ts b/packages/client/test/sim/sharding.spec.ts index 94d0532628..d73cc86eb1 100644 --- a/packages/client/test/sim/sharding.spec.ts +++ b/packages/client/test/sim/sharding.spec.ts @@ -106,8 +106,16 @@ tape('sharding/eip4844 hardfork tests', async (t) => { 4, 4096, pkey, - bytesToPrefixedHexString(randomBytes(20)), - undefined, + // Start with nonce of 1 since a tx previous has already been posted + 1, + { + to: bytesToPrefixedHexString(randomBytes(20)), + chainId: 1, + maxFeePerDataGas: BigInt(1000) as any, + maxPriorityFeePerGas: BigInt(1) as any, + maxFeePerGas: '0xff' as any, + gasLimit: BigInt(1000000) as any, + }, { common } ) const txHashes = [] diff --git a/packages/client/test/sim/simutils.ts b/packages/client/test/sim/simutils.ts index e410e14f21..1b3fc879aa 100644 --- a/packages/client/test/sim/simutils.ts +++ b/packages/client/test/sim/simutils.ts @@ -362,8 +362,16 @@ export const createBlobTxs = async ( numTxs: number, blobSize = 2 ** 17 - 1, pkey: Uint8Array, - to?: string, - value?: bigint, + startNonce: number = 0, + txMeta: { + to?: string + value?: bigint + chainId?: number + maxFeePerDataGas: bigint + maxPriorityFeePerGas: bigint + maxFeePerGas: bigint + gasLimit: bigint + }, opts?: TxOptions ) => { const txHashes: string[] = [] @@ -372,39 +380,29 @@ export const createBlobTxs = async ( const commitments = blobsToCommitments(blobs) const proofs = blobsToProofs(blobs, commitments) const hashes = commitmentsToVersionedHashes(commitments) + const txns = [] - for (let x = 1; x <= numTxs; x++) { + for (let x = startNonce; x <= startNonce + numTxs; x++) { const sender = Address.fromPrivateKey(pkey) const txData = { from: sender.toString(), - to, - data: '0x', - chainId: '0x1', + ...txMeta, blobs, kzgCommitments: commitments, kzgProofs: proofs, versionedHashes: hashes, - gas: undefined, - maxFeePerDataGas: undefined, - maxPriorityFeePerGas: undefined, - maxFeePerGas: undefined, nonce: BigInt(x), - gasLimit: undefined, - value, + gas: undefined, } - txData['maxFeePerGas'] = '0xff' as any - txData['maxPriorityFeePerGas'] = BigInt(1) as any - txData['maxFeePerDataGas'] = BigInt(1000) as any - txData['gasLimit'] = BigInt(1000000) as any - const blobTx = BlobEIP4844Transaction.fromTxData(txData, opts).sign(pkey) const serializedWrapper = blobTx.serializeNetworkWrapper() await fs.appendFile('./blobs.txt', bytesToPrefixedHexString(serializedWrapper) + '\n') + txns.push(bytesToPrefixedHexString(serializedWrapper)) txHashes.push(bytesToPrefixedHexString(blobTx.hash())) } - return txHashes + return txns } export const runBlobTxsFromFile = async (client: Client, path: string) => { From dd19ccfd7dd76bee7fb24a9014b1adc6f4056ab6 Mon Sep 17 00:00:00 2001 From: Holger Drewes Date: Mon, 8 May 2023 15:17:06 +0200 Subject: [PATCH 34/53] Trie: more conservative trie cache behavior (#2681) --- packages/trie/src/db/checkpoint.ts | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/packages/trie/src/db/checkpoint.ts b/packages/trie/src/db/checkpoint.ts index 6d033a5aae..982b8f7b91 100644 --- a/packages/trie/src/db/checkpoint.ts +++ b/packages/trie/src/db/checkpoint.ts @@ -158,16 +158,17 @@ export class CheckpointDB implements DB { */ async put(key: Uint8Array, value: Uint8Array): Promise { const keyHex = bytesToHex(key) - if (this._cache !== undefined) { - this._cache.set(keyHex, value) - this._stats.cache.writes += 1 - } if (this.hasCheckpoints()) { // put value in diff cache - this.checkpoints[this.checkpoints.length - 1].keyValueMap.set(bytesToHex(key), value) + this.checkpoints[this.checkpoints.length - 1].keyValueMap.set(keyHex, value) } else { await this.db.put(key, value) this._stats.db.writes += 1 + + if (this._cache !== undefined) { + this._cache.set(keyHex, value) + this._stats.cache.writes += 1 + } } } @@ -176,16 +177,18 @@ export class CheckpointDB implements DB { */ async del(key: Uint8Array): Promise { const keyHex = bytesToHex(key) - if (this._cache !== undefined) { - this._cache.set(keyHex, null) - this._stats.cache.writes += 1 - } if (this.hasCheckpoints()) { // delete the value in the current diff cache - this.checkpoints[this.checkpoints.length - 1].keyValueMap.set(bytesToHex(key), null) + this.checkpoints[this.checkpoints.length - 1].keyValueMap.set(keyHex, null) } else { // delete the value on disk await this.db.del(key) + this._stats.db.writes += 1 + + if (this._cache !== undefined) { + this._cache.set(keyHex, null) + this._stats.cache.writes += 1 + } } } From 8b84f5d828644b14f488c9e559d7f17feaf69f98 Mon Sep 17 00:00:00 2001 From: g11tech Date: Wed, 10 May 2023 19:50:21 +0530 Subject: [PATCH 35/53] evm: Fix the gasCost logs in op code trace (#2686) --- packages/evm/src/interpreter.ts | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/packages/evm/src/interpreter.ts b/packages/evm/src/interpreter.ts index 92dabbedbd..68908da11c 100644 --- a/packages/evm/src/interpreter.ts +++ b/packages/evm/src/interpreter.ts @@ -1,12 +1,5 @@ import { ConsensusAlgorithm } from '@ethereumjs/common' -import { - Account, - MAX_UINT64, - bigIntToHex, - bytesToBigInt, - bytesToHex, - intToHex, -} from '@ethereumjs/util' +import { Account, MAX_UINT64, bigIntToHex, bytesToBigInt, bytesToHex } from '@ethereumjs/util' import { debug as createDebugLogger } from 'debug' import { EOF } from './eof' @@ -331,7 +324,7 @@ export class Interpreter { pc: eventObj.pc, op: name, gas: bigIntToHex(eventObj.gasLeft), - gasCost: intToHex(eventObj.opcode.fee), + gasCost: bigIntToHex(dynamicFee), stack: hexStack, depth: eventObj.depth, } From 32ffec21b5b0e69bedbe7f1c13fba38e76732faf Mon Sep 17 00:00:00 2001 From: Jochem Brouwer Date: Thu, 11 May 2023 17:32:10 +0200 Subject: [PATCH 36/53] Remove EEI from EVM v2 (#2649) * statemanager/common: extract state manager interface to common evm: import eei vm: update changes to evm eei evm: fix test syntax evm: ensure default blockchain is loaded in tests vm/evm: fix vm test such that they run [no ci] vm: fix vm copy client/vm: fix build vm: fix test runner evm: fix example common: fix interface function sig stateManager/vm: fix tests client: fix tests client: fix tests evm: fix example * evm/tx/common/statemanager: move EEI logic into statemanager * evm: fix test runner * statemanager/vm: fix test runners [no ci] * vm: fix bugs regarding touched accounts * vm: fix api tests, update interface * evm: ensure accounts are touched * client: fix build * vm: move cleanup touched accounts check inside vm * vm: fix state test * vm: fix retesteth * vm: fix benchmarks * evm: fix test * util: lint * client: fix tests * evm/statemanager: remove unused methods + mark methods as private * evm/vm/state/common: extract statemanagerinterface * common: update interfaces * evm: remove enableDefaultBlockchain * vm: fix retesteth * ethersStateManager: disable tests * empty commit --------- Co-authored-by: acolytec3 <17355484+acolytec3@users.noreply.github.com> --- package-lock.json | 1 + packages/client/lib/execution/vmexecution.ts | 2 +- packages/client/lib/miner/miner.ts | 2 +- packages/client/lib/miner/pendingBlock.ts | 2 +- packages/client/lib/service/txpool.ts | 2 +- packages/client/test/miner/miner.spec.ts | 12 +- .../client/test/miner/pendingBlock.spec.ts | 9 +- .../client/test/rpc/eth/estimateGas.spec.ts | 2 +- .../client/test/rpc/eth/getBalance.spec.ts | 2 +- .../getBlockTransactionCountByNumber.spec.ts | 4 +- packages/client/test/rpc/eth/getCode.spec.ts | 2 +- .../test/rpc/eth/getTransactionCount.spec.ts | 2 +- .../client/test/rpc/txpool/content.spec.ts | 2 +- packages/client/test/sim/4844-devnet-5.md | 17 +- packages/client/test/sync/txpool.spec.ts | 4 +- packages/common/src/index.ts | 1 + packages/common/src/interfaces.ts | 94 ++++ packages/evm/examples/runCode.ts | 5 +- packages/evm/package.json | 2 + packages/evm/src/evm.ts | 102 ++-- packages/evm/src/index.ts | 4 +- packages/evm/src/interpreter.ts | 50 +- packages/evm/src/opcodes/EIP2929.ts | 16 +- packages/evm/src/opcodes/functions.ts | 14 +- packages/evm/src/opcodes/gas.ts | 12 +- packages/evm/src/types.ts | 109 +--- packages/evm/test/asyncEvents.spec.ts | 10 +- packages/evm/test/customOpcodes.spec.ts | 18 +- packages/evm/test/customPrecompiles.spec.ts | 25 +- packages/evm/test/eips/eip-3860.spec.ts | 82 +-- packages/evm/test/opcodes.spec.ts | 33 +- .../evm/test/precompiles/06-ecadd.spec.ts | 8 +- .../evm/test/precompiles/07-ecmul.spec.ts | 8 +- .../evm/test/precompiles/08-ecpairing.spec.ts | 8 +- .../precompiles/14-pointevaluation.spec.ts | 8 +- .../evm/test/precompiles/eip-2537-BLS.spec.ts | 20 +- .../evm/test/precompiles/hardfork.spec.ts | 20 +- packages/evm/test/runCall.spec.ts | 155 +++--- packages/evm/test/runCode.spec.ts | 32 +- packages/evm/test/stack.spec.ts | 14 +- packages/evm/test/utils.ts | 13 - .../src/cache}/journaling.ts | 0 .../statemanager/src/ethersStateManager.ts | 6 +- packages/statemanager/src/index.ts | 1 - packages/statemanager/src/interface.ts | 39 -- packages/statemanager/src/stateManager.ts | 415 ++++++++++++++- .../test/ethersStateManager.spec.ts | 12 +- .../statemanager/test/oldeeitests.spec.ts | 62 +++ .../api => statemanager/test}/vmState.spec.ts | 84 +-- packages/tx/src/types.ts | 26 +- packages/util/src/constants.ts | 2 + packages/vm/benchmarks/util.ts | 4 +- packages/vm/src/buildBlock.ts | 4 +- packages/vm/src/eei/eei.ts | 104 ---- packages/vm/src/eei/vmState.ts | 489 ------------------ packages/vm/src/index.ts | 1 - packages/vm/src/runBlock.ts | 22 +- packages/vm/src/runTx.ts | 30 +- packages/vm/src/types.ts | 14 +- packages/vm/src/vm.ts | 52 +- packages/vm/test/api/EIPs/eip-3529.spec.ts | 4 +- .../api/EIPs/eip-4895-withdrawals.spec.ts | 12 +- packages/vm/test/api/buildBlock.spec.ts | 2 +- packages/vm/test/api/eei.spec.ts | 115 ---- packages/vm/test/api/runBlock.spec.ts | 16 +- packages/vm/test/api/runTx.spec.ts | 104 ++-- .../vm/test/api/state/accountExists.spec.ts | 2 +- packages/vm/test/api/utils.ts | 10 +- .../vm/test/retesteth/transition-child.ts | 13 +- .../tester/runners/BlockchainTestsRunner.ts | 9 +- .../tester/runners/GeneralStateTestsRunner.ts | 29 +- packages/vm/test/util.ts | 4 +- 72 files changed, 1225 insertions(+), 1390 deletions(-) create mode 100644 packages/common/src/interfaces.ts rename packages/{vm/src/eei => statemanager/src/cache}/journaling.ts (100%) delete mode 100644 packages/statemanager/src/interface.ts create mode 100644 packages/statemanager/test/oldeeitests.spec.ts rename packages/{vm/test/api => statemanager/test}/vmState.spec.ts (84%) delete mode 100644 packages/vm/src/eei/eei.ts delete mode 100644 packages/vm/src/eei/vmState.ts delete mode 100644 packages/vm/test/api/eei.spec.ts diff --git a/package-lock.json b/package-lock.json index 6d015a9a9b..dbb9c85ec4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18128,6 +18128,7 @@ "license": "MPL-2.0", "dependencies": { "@ethereumjs/common": "^3.1.1", + "@ethereumjs/tx": "^4.1.1", "@ethereumjs/util": "^8.0.5", "debug": "^4.3.3", "ethereum-cryptography": "^1.1.2", diff --git a/packages/client/lib/execution/vmexecution.ts b/packages/client/lib/execution/vmexecution.ts index 6036721dd3..83b82a48f5 100644 --- a/packages/client/lib/execution/vmexecution.ts +++ b/packages/client/lib/execution/vmexecution.ts @@ -136,7 +136,7 @@ export class VMExecution extends Execution { if (typeof this.vm.blockchain.genesisState !== 'function') { throw new Error('cannot get iterator head: blockchain has no genesisState function') } - await this.vm.eei.generateCanonicalGenesis(this.vm.blockchain.genesisState()) + await this.vm.stateManager.generateCanonicalGenesis(this.vm.blockchain.genesisState()) } await super.open() // TODO: Should a run be started to execute any left over blocks? diff --git a/packages/client/lib/miner/miner.ts b/packages/client/lib/miner/miner.ts index ba673c2e05..a2695b4d3c 100644 --- a/packages/client/lib/miner/miner.ts +++ b/packages/client/lib/miner/miner.ts @@ -237,7 +237,7 @@ export class Miner { // Set the state root to ensure the resulting state // is based on the parent block's state - await vmCopy.eei.setStateRoot(parentBlock.header.stateRoot) + await vmCopy.stateManager.setStateRoot(parentBlock.header.stateRoot) let difficulty let cliqueSigner diff --git a/packages/client/lib/miner/pendingBlock.ts b/packages/client/lib/miner/pendingBlock.ts index 0b8ea879e9..7eafe5a68b 100644 --- a/packages/client/lib/miner/pendingBlock.ts +++ b/packages/client/lib/miner/pendingBlock.ts @@ -128,7 +128,7 @@ export class PendingBlock { // Set the state root to ensure the resulting state // is based on the parent block's state - await vm.eei.setStateRoot(parentBlock.header.stateRoot) + await vm.stateManager.setStateRoot(parentBlock.header.stateRoot) const builder = await vm.buildBlock({ parentBlock, diff --git a/packages/client/lib/service/txpool.ts b/packages/client/lib/service/txpool.ts index e9a59b261c..1fbe5caae8 100644 --- a/packages/client/lib/service/txpool.ts +++ b/packages/client/lib/service/txpool.ts @@ -700,7 +700,7 @@ export class TxPool { .map((obj) => obj.tx) .sort((a, b) => Number(a.nonce - b.nonce)) // Check if the account nonce matches the lowest known tx nonce - let account = await vm.eei.getAccount(new Address(hexStringToBytes(address))) + let account = await vm.stateManager.getAccount(new Address(hexStringToBytes(address))) if (account === undefined) { account = new Account() } diff --git a/packages/client/test/miner/miner.spec.ts b/packages/client/test/miner/miner.spec.ts index cd77e23e34..6cfab9709d 100644 --- a/packages/client/test/miner/miner.spec.ts +++ b/packages/client/test/miner/miner.spec.ts @@ -3,7 +3,6 @@ import { Common, Chain as CommonChain, Hardfork } from '@ethereumjs/common' import { DefaultStateManager } from '@ethereumjs/statemanager' import { FeeMarketEIP1559Transaction, Transaction } from '@ethereumjs/tx' import { Address, equalsBytes, hexStringToBytes } from '@ethereumjs/util' -import { VmState } from '@ethereumjs/vm/dist/eei/vmState' import { AbstractLevel } from 'abstract-level' import { keccak256 } from 'ethereum-cryptography/keccak' import * as tape from 'tape' @@ -31,9 +30,9 @@ const B = { } const setBalance = async (vm: VM, address: Address, balance: bigint) => { - await vm.eei.checkpoint() - await vm.eei.modifyAccountFields(address, { balance }) - await vm.eei.commit() + await vm.stateManager.checkpoint() + await vm.stateManager.modifyAccountFields(address, { balance }) + await vm.stateManager.commit() } tape('[Miner]', async (t) => { @@ -41,10 +40,6 @@ tape('[Miner]', async (t) => { BlockHeader.prototype._consensusFormatValidation = td.func() td.replace('@ethereumjs/block', { BlockHeader }) - const originalSetStateRoot = VmState.prototype.setStateRoot - VmState.prototype.setStateRoot = td.func() - td.replace('@ethereumjs/vm/dist/vmState', { VmState }) - // Stub out setStateRoot so txPool.validate checks will pass since correct state root // doesn't exist in fakeChain state anyway const ogStateManagerSetStateRoot = DefaultStateManager.prototype.setStateRoot @@ -620,7 +615,6 @@ tape('[Miner]', async (t) => { // mocking indirect dependencies is not properly supported, but it works for us in this file, // so we will replace the original functions to avoid issues in other tests that come after BlockHeader.prototype._consensusFormatValidation = originalValidate - VmState.prototype.setStateRoot = originalSetStateRoot DefaultStateManager.prototype.setStateRoot = ogStateManagerSetStateRoot t.end() }) diff --git a/packages/client/test/miner/pendingBlock.spec.ts b/packages/client/test/miner/pendingBlock.spec.ts index 890c63b47a..54a556e3e1 100644 --- a/packages/client/test/miner/pendingBlock.spec.ts +++ b/packages/client/test/miner/pendingBlock.spec.ts @@ -1,5 +1,6 @@ import { Block, BlockHeader } from '@ethereumjs/block' import { Common, Chain as CommonChain, Hardfork } from '@ethereumjs/common' +import { DefaultStateManager } from '@ethereumjs/statemanager' import { BlobEIP4844Transaction, FeeMarketEIP1559Transaction, Transaction } from '@ethereumjs/tx' import { Account, @@ -16,7 +17,6 @@ import { randomBytes, } from '@ethereumjs/util' import { VM } from '@ethereumjs/vm' -import { VmState } from '@ethereumjs/vm/dist/eei/vmState' import * as kzg from 'c-kzg' import * as tape from 'tape' import * as td from 'testdouble' @@ -83,9 +83,8 @@ tape('[PendingBlock]', async (t) => { BlockHeader.prototype._consensusFormatValidation = td.func() td.replace('@ethereumjs/block', { BlockHeader }) - const originalSetStateRoot = VmState.prototype.setStateRoot - VmState.prototype.setStateRoot = td.func() - td.replace('@ethereumjs/vm/dist/vmState', { VmState }) + const originalSetStateRoot = DefaultStateManager.prototype.setStateRoot + DefaultStateManager.prototype.setStateRoot = td.func() const createTx = ( from = A, @@ -344,7 +343,7 @@ tape('[PendingBlock]', async (t) => { // mocking indirect dependencies is not properly supported, but it works for us in this file, // so we will replace the original functions to avoid issues in other tests that come after BlockHeader.prototype._consensusFormatValidation = originalValidate - VmState.prototype.setStateRoot = originalSetStateRoot + DefaultStateManager.prototype.setStateRoot = originalSetStateRoot st.end() }) diff --git a/packages/client/test/rpc/eth/estimateGas.spec.ts b/packages/client/test/rpc/eth/estimateGas.spec.ts index d12d1af4cd..5916ee35d6 100644 --- a/packages/client/test/rpc/eth/estimateGas.spec.ts +++ b/packages/client/test/rpc/eth/estimateGas.spec.ts @@ -30,7 +30,7 @@ tape(`${method}: call with valid arguments`, async (t) => { const { execution } = client.services.find((s) => s.name === 'eth') as FullEthereumService t.notEqual(execution, undefined, 'should have valid execution') const { vm } = execution - await vm.eei.generateCanonicalGenesis(blockchain.genesisState()) + await vm.stateManager.generateCanonicalGenesis(blockchain.genesisState()) // genesis address with balance const address = Address.fromString('0xccfd725760a68823ff1e062f4cc97e1360e8d997') diff --git a/packages/client/test/rpc/eth/getBalance.spec.ts b/packages/client/test/rpc/eth/getBalance.spec.ts index af2ba67209..a36a491503 100644 --- a/packages/client/test/rpc/eth/getBalance.spec.ts +++ b/packages/client/test/rpc/eth/getBalance.spec.ts @@ -28,7 +28,7 @@ tape(`${method}: ensure balance deducts after a tx`, async (t) => { // since synchronizer.run() is not executed in the mock setup, // manually run stateManager.generateCanonicalGenesis() - await vm.eei.generateCanonicalGenesis(blockchain.genesisState()) + await vm.stateManager.generateCanonicalGenesis(blockchain.genesisState()) // genesis address with balance const address = Address.fromString('0xccfd725760a68823ff1e062f4cc97e1360e8d997') diff --git a/packages/client/test/rpc/eth/getBlockTransactionCountByNumber.spec.ts b/packages/client/test/rpc/eth/getBlockTransactionCountByNumber.spec.ts index 870ac68b73..04d25afbca 100644 --- a/packages/client/test/rpc/eth/getBlockTransactionCountByNumber.spec.ts +++ b/packages/client/test/rpc/eth/getBlockTransactionCountByNumber.spec.ts @@ -30,7 +30,7 @@ tape(`${method}: call with valid arguments`, async (t) => { t.notEqual(execution, undefined, 'should have valid execution') const { vm } = execution - await vm.eei.generateCanonicalGenesis(blockchain.genesisState()) + await vm.stateManager.generateCanonicalGenesis(blockchain.genesisState()) const address = Address.fromString('0xccfd725760a68823ff1e062f4cc97e1360e8d997') @@ -81,7 +81,7 @@ tape(`${method}: call with valid arguments (multiple transactions)`, async (t) = t.notEqual(execution, undefined, 'should have valid execution') const { vm } = execution - await vm.eei.generateCanonicalGenesis(blockchain.genesisState()) + await vm.stateManager.generateCanonicalGenesis(blockchain.genesisState()) const address = Address.fromString('0xccfd725760a68823ff1e062f4cc97e1360e8d997') diff --git a/packages/client/test/rpc/eth/getCode.spec.ts b/packages/client/test/rpc/eth/getCode.spec.ts index ef9ac9803a..e84799a558 100644 --- a/packages/client/test/rpc/eth/getCode.spec.ts +++ b/packages/client/test/rpc/eth/getCode.spec.ts @@ -25,7 +25,7 @@ tape(`${method}: call with valid arguments`, async (t) => { const { execution } = client.services.find((s) => s.name === 'eth') as FullEthereumService t.notEqual(execution, undefined, 'should have valid execution') const { vm } = execution - await vm.eei.generateCanonicalGenesis(blockchain.genesisState()) + await vm.stateManager.generateCanonicalGenesis(blockchain.genesisState()) // genesis address const address = Address.fromString('0xccfd725760a68823ff1e062f4cc97e1360e8d997') diff --git a/packages/client/test/rpc/eth/getTransactionCount.spec.ts b/packages/client/test/rpc/eth/getTransactionCount.spec.ts index e9a4d0fab4..b5b4bd59f5 100644 --- a/packages/client/test/rpc/eth/getTransactionCount.spec.ts +++ b/packages/client/test/rpc/eth/getTransactionCount.spec.ts @@ -32,7 +32,7 @@ tape(`${method}: call with valid arguments`, async (t) => { // since synchronizer.run() is not executed in the mock setup, // manually run stateManager.generateCanonicalGenesis() - await vm.eei.generateCanonicalGenesis(blockchain.genesisState()) + await vm.stateManager.generateCanonicalGenesis(blockchain.genesisState()) // a genesis address const address = Address.fromString('0xccfd725760a68823ff1e062f4cc97e1360e8d997') diff --git a/packages/client/test/rpc/txpool/content.spec.ts b/packages/client/test/rpc/txpool/content.spec.ts index 4585eaf8bf..19982167aa 100644 --- a/packages/client/test/rpc/txpool/content.spec.ts +++ b/packages/client/test/rpc/txpool/content.spec.ts @@ -25,7 +25,7 @@ tape(`${method}: call with valid arguments`, async (t) => { const { execution } = client.services.find((s) => s.name === 'eth') as FullEthereumService t.notEqual(execution, undefined, 'should have valid execution') const { vm } = execution - await vm.eei.generateCanonicalGenesis(blockchain.genesisState()) + await vm.stateManager.generateCanonicalGenesis(blockchain.genesisState()) const gasLimit = 2000000 const parent = await blockchain.getCanonicalHeadHeader() const block = Block.fromBlockData( diff --git a/packages/client/test/sim/4844-devnet-5.md b/packages/client/test/sim/4844-devnet-5.md index b48cedf802..f91d2f1245 100644 --- a/packages/client/test/sim/4844-devnet-5.md +++ b/packages/client/test/sim/4844-devnet-5.md @@ -4,14 +4,15 @@ how to run: 1. Clone the repo set to branch `develop-v7` and run `npm i` with nodejs `18` installed and latest npm version 2. Run the blob gen utility (replace PRIVATE_KEY with a funded account private key and RPC_URL with an authenticated rpc url): - ```typescript - cd packages/client - PRIVATE_KEY=ae557af4ceefda559c924516cabf029bedc36b68109bf8d6183fe96e04121f4e RPC_URL=https://rpc.lodestar-ethereumjs-1.srv.4844-devnet-5.ethpandaops.io npm run tape -- test/sim/4844devnet5.spec.ts - ``` - It runs with current chainId of `4844001005`, if you want to override pass `CHAIN_ID=` env param in above command - currently it posts 2 txs, but that can be modified with another env variable `NUM_TXS` +```typescript + cd packages/client + PRIVATE_KEY=ae557af4ceefda559c924516cabf029bedc36b68109bf8d6183fe96e04121f4e RPC_URL=https://rpc.lodestar-ethereumjs-1.srv.4844-devnet-5.ethpandaops.io npm run tape -- test/sim/4844devnet5.spec.ts +``` - You can manipulate the fees for the txs using env variables in the following way (for e.g. to replace a low fee stuck tx): +It runs with current chainId of `4844001005`, if you want to override pass `CHAIN_ID=` env param in above command +currently it posts 2 txs, but that can be modified with another env variable `NUM_TXS` - `GAS_LIMIT=0xffffff MAX_FEE=1000000000 MAX_PRIORITY=100000000 MAX_DATAFEE=100000000 RIVATE_KEY=ae557af4ceefda559c924516cabf029bedc36b68109bf8d6183fe96e04121f4e RPC_URL=https://rpc.lodestar-ethereumjs-1.srv.4844-devnet-5.ethpandaops.io npm run tape -- test/sim/4844devnet5.spec.ts` +You can manipulate the fees for the txs using env variables in the following way (for e.g. to replace a low fee stuck tx): + +`GAS_LIMIT=0xffffff MAX_FEE=1000000000 MAX_PRIORITY=100000000 MAX_DATAFEE=100000000 RIVATE_KEY=ae557af4ceefda559c924516cabf029bedc36b68109bf8d6183fe96e04121f4e RPC_URL=https://rpc.lodestar-ethereumjs-1.srv.4844-devnet-5.ethpandaops.io npm run tape -- test/sim/4844devnet5.spec.ts` diff --git a/packages/client/test/sync/txpool.spec.ts b/packages/client/test/sync/txpool.spec.ts index a3cc5dd907..a412434df1 100644 --- a/packages/client/test/sync/txpool.spec.ts +++ b/packages/client/test/sync/txpool.spec.ts @@ -16,8 +16,6 @@ import { getLogger } from '../../lib/logging' import { PeerPool } from '../../lib/net/peerpool' import { TxPool } from '../../lib/service/txpool' -import type { StateManager } from '@ethereumjs/statemanager' - const setup = () => { const config = new Config({ transports: [], @@ -50,7 +48,7 @@ const config = new Config({ transports: [], accountCache: 10000, storageCache: 1 const handleTxs = async ( txs: any[], failMessage: string, - stateManager?: StateManager, + stateManager?: DefaultStateManager, pool?: TxPool ) => { if (pool === undefined) { diff --git a/packages/common/src/index.ts b/packages/common/src/index.ts index ce4da6d414..87517979ee 100644 --- a/packages/common/src/index.ts +++ b/packages/common/src/index.ts @@ -1,4 +1,5 @@ export * from './common' export * from './enums' +export * from './interfaces' export * from './types' export * from './utils' diff --git a/packages/common/src/interfaces.ts b/packages/common/src/interfaces.ts new file mode 100644 index 0000000000..9cded65aa7 --- /dev/null +++ b/packages/common/src/interfaces.ts @@ -0,0 +1,94 @@ +import type { Account, Address, PrefixedHexString } from '@ethereumjs/util' + +export interface StorageDump { + [key: string]: string +} + +export type AccountFields = Partial> + +export type StorageProof = { + key: PrefixedHexString + proof: PrefixedHexString[] + value: PrefixedHexString +} + +export type Proof = { + address: PrefixedHexString + balance: PrefixedHexString + codeHash: PrefixedHexString + nonce: PrefixedHexString + storageHash: PrefixedHexString + accountProof: PrefixedHexString[] + storageProof: StorageProof[] +} + +/* + * Access List types + */ + +export type AccessListItem = { + address: PrefixedHexString + storageKeys: PrefixedHexString[] +} + +/* + * An Access List as a tuple of [address: Uint8Array, storageKeys: Uint8Array[]] + */ +export type AccessListBytesItem = [Uint8Array, Uint8Array[]] +export type AccessListBytes = AccessListBytesItem[] +export type AccessList = AccessListItem[] + +export interface StateManagerInterface { + accountExists(address: Address): Promise + getAccount(address: Address): Promise + putAccount(address: Address, account: Account): Promise + deleteAccount(address: Address): Promise + modifyAccountFields(address: Address, accountFields: AccountFields): Promise + putContractCode(address: Address, value: Uint8Array): Promise + getContractCode(address: Address): Promise + getContractStorage(address: Address, key: Uint8Array): Promise + putContractStorage(address: Address, key: Uint8Array, value: Uint8Array): Promise + clearContractStorage(address: Address): Promise + checkpoint(): Promise + commit(): Promise + revert(): Promise + getStateRoot(): Promise + setStateRoot(stateRoot: Uint8Array, clearCache?: boolean): Promise + getProof?(address: Address, storageSlots: Uint8Array[]): Promise + hasStateRoot(root: Uint8Array): Promise // only used in client + copy(): StateManagerInterface +} + +export interface EVMStateManagerInterface extends StateManagerInterface { + // TODO check if all these `touch?` interfaces can be moved into StateManagerInterface + putAccount(address: Address, account: Account, touch?: boolean): Promise + deleteAccount(address: Address, touch?: boolean): Promise + accountIsEmptyOrNonExistent(address: Address): Promise + + getOriginalContractStorage(address: Address, key: Uint8Array): Promise + + dumpStorage(address: Address): Promise // only used in client + putContractStorage( + address: Address, + key: Uint8Array, + value: Uint8Array, + touch?: boolean + ): Promise + + clearContractStorage(address: Address, touch?: boolean): Promise + + clearWarmedAccounts(): void + cleanupTouchedAccounts(): Promise + clearOriginalStorageCache(): void + + addWarmedAddress(address: Uint8Array): void + isWarmedAddress(address: Uint8Array): boolean + addWarmedStorage(address: Uint8Array, slot: Uint8Array): void + isWarmedStorage(address: Uint8Array, slot: Uint8Array): boolean + + generateCanonicalGenesis(initState: any): Promise // TODO make input more typesafe + generateAccessList(addressesRemoved: Address[], addressesOnlyStorage: Address[]): AccessList + getProof(address: Address, storageSlots?: Uint8Array[]): Promise + + copy(): EVMStateManagerInterface +} diff --git a/packages/evm/examples/runCode.ts b/packages/evm/examples/runCode.ts index 96a843a8c3..34695c8a4b 100644 --- a/packages/evm/examples/runCode.ts +++ b/packages/evm/examples/runCode.ts @@ -2,18 +2,17 @@ import { Blockchain } from '@ethereumjs/blockchain' import { Chain, Common, Hardfork } from '@ethereumjs/common' import { EVM } from '@ethereumjs/evm' import { DefaultStateManager } from '@ethereumjs/statemanager' -import { EEI } from '@ethereumjs/vm' import { bytesToHex, hexToBytes } from 'ethereum-cryptography/utils' const main = async () => { const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.London }) const stateManager = new DefaultStateManager() const blockchain = await Blockchain.create() - const eei = new EEI(stateManager, common, blockchain) const evm = new EVM({ common, - eei, + stateManager, + blockchain, }) const STOP = '00' diff --git a/packages/evm/package.json b/packages/evm/package.json index 7152de7605..e0ad5a7422 100644 --- a/packages/evm/package.json +++ b/packages/evm/package.json @@ -47,6 +47,7 @@ "tsc": "../../config/cli/ts-compile.sh" }, "dependencies": { + "@ethereumjs/statemanager": "^1.0.4", "@ethereumjs/common": "^3.1.1", "@ethereumjs/util": "^8.0.5", "debug": "^4.3.3", @@ -55,6 +56,7 @@ "rustbn.js": "~0.2.0" }, "devDependencies": { + "@ethersproject/abi": "^5.0.12", "@ethereumjs/statemanager": "^1.0.4", "@types/benchmark": "^1.0.33", "@types/core-js": "^2.5.0", diff --git a/packages/evm/src/evm.ts b/packages/evm/src/evm.ts index 557d9bf7c6..fa559d9b26 100644 --- a/packages/evm/src/evm.ts +++ b/packages/evm/src/evm.ts @@ -1,4 +1,5 @@ import { Chain, Common, Hardfork } from '@ethereumjs/common' +import { DefaultStateManager } from '@ethereumjs/statemanager' import { Account, Address, @@ -23,6 +24,7 @@ import { Message } from './message' import { getOpcodesForHF } from './opcodes' import { getActivePrecompiles } from './precompiles' import { TransientStorage } from './transientStorage' +import { DefaultBlockchain } from './types' import type { InterpreterOpts, RunState } from './interpreter' import type { MessageWithTo } from './message' @@ -31,16 +33,15 @@ import type { AsyncDynamicGasHandler, SyncDynamicGasHandler } from './opcodes/ga import type { CustomPrecompile, PrecompileFunc } from './precompiles' import type { Block, + Blockchain, CustomOpcode, - EEIInterface, EVMEvents, EVMInterface, EVMRunCallOpts, EVMRunCodeOpts, - /*ExternalInterface,*/ - /*ExternalInterfaceFactory,*/ Log, } from './types' +import type { EVMStateManagerInterface } from '@ethereumjs/common' const debug = createDebugLogger('evm:evm') const debugGas = createDebugLogger('evm:gas') @@ -137,9 +138,14 @@ export interface EVMOpts { customPrecompiles?: CustomPrecompile[] /* - * The External Interface Factory, used to build an External Interface when this is necessary + * The StateManager which is used to update the trie */ - eei: EEIInterface + stateManager: EVMStateManagerInterface + + /** + * + */ + blockchain?: Blockchain } /** @@ -177,7 +183,8 @@ export class EVM implements EVMInterface { readonly _common: Common - public eei: EEIInterface + public stateManager: EVMStateManagerInterface + public blockchain: Blockchain public readonly _transientStorage: TransientStorage @@ -254,8 +261,6 @@ export class EVM implements EVMInterface { this._optsCached = opts - this.eei = opts.eei - this._transientStorage = new TransientStorage() if (opts.common) { @@ -265,6 +270,17 @@ export class EVM implements EVMInterface { this._common = new Common({ chain: DEFAULT_CHAIN }) } + let blockchain: Blockchain + + if (opts.blockchain === undefined) { + blockchain = new DefaultBlockchain() + } else { + blockchain = opts.blockchain + } + + this.blockchain = blockchain + this.stateManager = opts.stateManager ?? new DefaultStateManager() + // Supported EIPs const supportedEIPs = [ 1153, 1559, 2315, 2537, 2565, 2718, 2929, 2930, 3074, 3198, 3529, 3540, 3541, 3607, 3651, @@ -348,7 +364,7 @@ export class EVM implements EVMInterface { } protected async _executeCall(message: MessageWithTo): Promise { - let account = await this.eei.getAccount(message.authcallOrigin ?? message.caller) + let account = await this.stateManager.getAccount(message.authcallOrigin ?? message.caller) if (!account) { account = new Account() } @@ -362,7 +378,7 @@ export class EVM implements EVMInterface { } } // Load `to` account - let toAccount = await this.eei.getAccount(message.to) + let toAccount = await this.stateManager.getAccount(message.to) if (!toAccount) { toAccount = new Account() } @@ -426,7 +442,7 @@ export class EVM implements EVMInterface { } protected async _executeCreate(message: Message): Promise { - let account = await this.eei.getAccount(message.caller) + let account = await this.stateManager.getAccount(message.caller) if (!account) { account = new Account() } @@ -455,7 +471,7 @@ export class EVM implements EVMInterface { if (this.DEBUG) { debug(`Generated CREATE contract address ${message.to}`) } - let toAccount = await this.eei.getAccount(message.to) + let toAccount = await this.stateManager.getAccount(message.to) if (!toAccount) { toAccount = new Account() } @@ -478,8 +494,8 @@ export class EVM implements EVMInterface { } } - await this.eei.putAccount(message.to, toAccount) - await this.eei.clearContractStorage(message.to) + await this.stateManager.putAccount(message.to, toAccount, true) + await this.stateManager.clearContractStorage(message.to, true) const newContractEvent = { address: message.to, @@ -488,7 +504,7 @@ export class EVM implements EVMInterface { await this._emit('newContract', newContractEvent) - toAccount = await this.eei.getAccount(message.to) + toAccount = await this.stateManager.getAccount(message.to) if (!toAccount) { toAccount = new Account() } @@ -621,7 +637,7 @@ export class EVM implements EVMInterface { result.returnValue !== undefined && result.returnValue.length !== 0 ) { - await this.eei.putContractCode(message.to, result.returnValue) + await this.stateManager.putContractCode(message.to, result.returnValue) if (this.DEBUG) { debug(`Code saved on new contract creation`) } @@ -632,8 +648,8 @@ export class EVM implements EVMInterface { // This contract would be considered "DEAD" in later hard forks. // It is thus an unnecessary default item, which we have to save to disk // It does change the state root, but it only wastes storage. - const account = await this.eei.getAccount(message.to) - await this.eei.putAccount(message.to, account ?? new Account()) + const account = await this.stateManager.getAccount(message.to) + await this.stateManager.putAccount(message.to, account ?? new Account(), true) } } @@ -651,7 +667,7 @@ export class EVM implements EVMInterface { message: Message, opts: InterpreterOpts = {} ): Promise { - let contract = await this.eei.getAccount(message.to ?? Address.zero()) + let contract = await this.stateManager.getAccount(message.to ?? Address.zero()) if (!contract) { contract = new Account() } @@ -673,7 +689,13 @@ export class EVM implements EVMInterface { versionedHashes: message.versionedHashes ?? [], } - const interpreter = new Interpreter(this, this.eei, env, message.gasLimit) + const interpreter = new Interpreter( + this, + this.stateManager, + this.blockchain, + env, + message.gasLimit + ) if (message.selfdestruct) { interpreter._result.selfdestruct = message.selfdestruct as { [key: string]: Uint8Array } } @@ -731,14 +753,14 @@ export class EVM implements EVMInterface { const value = opts.value ?? BigInt(0) if (opts.skipBalance === true) { - callerAccount = await this.eei.getAccount(caller) + callerAccount = await this.stateManager.getAccount(caller) if (!callerAccount) { callerAccount = new Account() } if (callerAccount.balance < value) { // if skipBalance and balance less than value, set caller balance to `value` to ensure sufficient funds callerAccount.balance = value - await this.eei.putAccount(caller, callerAccount) + await this.stateManager.putAccount(caller, callerAccount, true) } } @@ -761,13 +783,13 @@ export class EVM implements EVMInterface { if (message.depth === 0) { if (!callerAccount) { - callerAccount = await this.eei.getAccount(message.caller) + callerAccount = await this.stateManager.getAccount(message.caller) } if (!callerAccount) { callerAccount = new Account() } callerAccount.nonce++ - await this.eei.putAccount(message.caller, callerAccount) + await this.stateManager.putAccount(message.caller, callerAccount, true) if (this.DEBUG) { debug(`Update fromAccount (caller) nonce (-> ${callerAccount.nonce}))`) } @@ -777,10 +799,10 @@ export class EVM implements EVMInterface { if (!message.to && this._common.isActivatedEIP(2929) === true) { message.code = message.data - this.eei.addWarmedAddress((await this._generateAddress(message)).bytes) + this.stateManager.addWarmedAddress((await this._generateAddress(message)).bytes) } - await this.eei.checkpoint() + await this.stateManager.checkpoint() if (this._common.isActivatedEIP(1153)) this._transientStorage.checkpoint() if (this.DEBUG) { debug('-'.repeat(100)) @@ -830,13 +852,13 @@ export class EVM implements EVMInterface { !(this._common.hardfork() === Hardfork.Chainstart && err.error === ERROR.CODESTORE_OUT_OF_GAS) ) { result.execResult.logs = [] - await this.eei.revert() + await this.stateManager.revert() if (this._common.isActivatedEIP(1153)) this._transientStorage.revert() if (this.DEBUG) { debug(`message checkpoint reverted`) } } else { - await this.eei.commit() + await this.stateManager.commit() if (this._common.isActivatedEIP(1153)) this._transientStorage.commit() if (this.DEBUG) { debug(`message checkpoint committed`) @@ -913,7 +935,7 @@ export class EVM implements EVMInterface { message.code = precompile message.isCompiled = true } else { - message.containerCode = await this.eei.getContractCode(message.codeAddress) + message.containerCode = await this.stateManager.getContractCode(message.codeAddress) message.isCompiled = false if (this._common.isActivatedEIP(3540)) { message.code = getEOFCode(message.containerCode) @@ -929,7 +951,7 @@ export class EVM implements EVMInterface { if (message.salt) { addr = generateAddress2(message.caller.bytes, message.salt, message.code as Uint8Array) } else { - let acc = await this.eei.getAccount(message.caller) + let acc = await this.stateManager.getAccount(message.caller) if (!acc) { acc = new Account() } @@ -944,7 +966,11 @@ export class EVM implements EVMInterface { if (account.balance < BigInt(0)) { throw new EvmError(ERROR.INSUFFICIENT_BALANCE) } - const result = this.eei.putAccount(message.authcallOrigin ?? message.caller, account) + const result = this.stateManager.putAccount( + message.authcallOrigin ?? message.caller, + account, + true + ) if (this.DEBUG) { debug(`Reduced sender (${message.caller}) balance (-> ${account.balance})`) } @@ -958,21 +984,13 @@ export class EVM implements EVMInterface { } toAccount.balance = newBalance // putAccount as the nonce may have changed for contract creation - const result = this.eei.putAccount(message.to, toAccount) + const result = this.stateManager.putAccount(message.to, toAccount, true) if (this.DEBUG) { debug(`Added toAccount (${message.to}) balance (-> ${toAccount.balance})`) } return result } - protected async _touchAccount(address: Address): Promise { - let account = await this.eei.getAccount(address) - if (!account) { - account = new Account() - } - return this.eei.putAccount(address, account) - } - /** * Once the interpreter has finished depth 0, a post-message cleanup should be done */ @@ -987,9 +1005,9 @@ export class EVM implements EVMInterface { const opts = { ...this._optsCached, common, - eei: this.eei.copy(), + stateManager: this.stateManager.copy(), } - ;(opts.eei as any)._common = common + ;(opts.stateManager as any)._common = common return new EVM(opts) } } diff --git a/packages/evm/src/index.ts b/packages/evm/src/index.ts index 449e68e97d..77918a440a 100644 --- a/packages/evm/src/index.ts +++ b/packages/evm/src/index.ts @@ -3,15 +3,13 @@ import { EvmError, ERROR as EvmErrorMessage } from './exceptions' import { InterpreterStep } from './interpreter' import { Message } from './message' import { getActivePrecompiles } from './precompiles' -import { EEIInterface, EVMInterface, EVMStateAccess, Log } from './types' +import { EVMInterface, Log } from './types' export { - EEIInterface, EVM, EvmError, EvmErrorMessage, EVMInterface, EVMResult, - EVMStateAccess, ExecResult, getActivePrecompiles, InterpreterStep, diff --git a/packages/evm/src/interpreter.ts b/packages/evm/src/interpreter.ts index 68908da11c..0c20f0ade9 100644 --- a/packages/evm/src/interpreter.ts +++ b/packages/evm/src/interpreter.ts @@ -11,8 +11,8 @@ import { Stack } from './stack' import type { EVM, EVMResult } from './evm' import type { AsyncOpHandler, OpHandler, Opcode } from './opcodes' -import type { Block, EEIInterface, Log } from './types' -import type { Common } from '@ethereumjs/common' +import type { Block, Blockchain, Log } from './types' +import type { Common, EVMStateManagerInterface } from '@ethereumjs/common' import type { Address } from '@ethereumjs/util' const debugGas = createDebugLogger('evm:eei:gas') @@ -62,7 +62,8 @@ export interface RunState { code: Uint8Array shouldDoJumpAnalysis: boolean validJumps: Uint8Array // array of values where validJumps[index] has value 0 (default), 1 (jumpdest), 2 (beginsub) - eei: EEIInterface + stateManager: EVMStateManagerInterface + blockchain: Blockchain env: Env messageGasLimit?: bigint // Cache value from `gas.ts` to save gas limit for a message call interpreter: Interpreter @@ -80,7 +81,7 @@ export interface InterpreterResult { export interface InterpreterStep { gasLeft: bigint gasRefund: bigint - eei: EEIInterface + stateManager: EVMStateManagerInterface stack: bigint[] returnStack: bigint[] pc: number @@ -104,7 +105,7 @@ export interface InterpreterStep { export class Interpreter { protected _vm: any protected _runState: RunState - protected _eei: EEIInterface + protected _stateManager: EVMStateManagerInterface protected _common: Common public _evm: EVM _env: Env @@ -119,9 +120,15 @@ export class Interpreter { // TODO remove eei from constructor this can be directly read from EVM // EEI gets created on EVM creation and will not be re-instantiated // TODO remove gasLeft as constructor argument - constructor(evm: EVM, eei: EEIInterface, env: Env, gasLeft: bigint) { + constructor( + evm: EVM, + stateManager: EVMStateManagerInterface, + blockchain: Blockchain, + env: Env, + gasLeft: bigint + ) { this._evm = evm - this._eei = eei + this._stateManager = stateManager this._common = this._evm._common this._runState = { programCounter: 0, @@ -133,7 +140,8 @@ export class Interpreter { returnStack: new Stack(1023), // 1023 return stack height limit per EIP 2315 spec code: new Uint8Array(0), validJumps: Uint8Array.from([]), - eei: this._eei, + stateManager: this._stateManager, + blockchain, env, shouldDoJumpAnalysis: true, interpreter: this, @@ -308,7 +316,7 @@ export class Interpreter { memory: this._runState.memory._store.subarray(0, Number(this._runState.memoryWordCount) * 32), memoryWordCount: this._runState.memoryWordCount, codeAddress: this._env.codeAddress, - eei: this._runState.eei, + stateManager: this._runState.stateManager, } if (this._evm.DEBUG) { @@ -465,7 +473,7 @@ export class Interpreter { return this._env.contract.balance } - let account = await this._eei.getAccount(address) + let account = await this._stateManager.getAccount(address) if (!account) { account = new Account() } @@ -476,8 +484,8 @@ export class Interpreter { * Store 256-bit a value in memory to persistent storage. */ async storageStore(key: Uint8Array, value: Uint8Array): Promise { - await this._eei.storageStore(this._env.address, key, value) - const account = await this._eei.getAccount(this._env.address) + await this._stateManager.putContractStorage(this._env.address, key, value, true) + const account = await this._stateManager.getAccount(this._env.address) if (!account) { throw new Error('could not read account while persisting memory') } @@ -490,7 +498,11 @@ export class Interpreter { * @param original - If true, return the original storage value (default: false) */ async storageLoad(key: Uint8Array, original = false): Promise { - return this._eei.storageLoad(this._env.address, key, original) + if (original) { + return this._stateManager.getOriginalContractStorage(this._env.address, key) + } else { + return this._stateManager.getContractStorage(this._env.address, key) + } } /** @@ -856,7 +868,7 @@ export class Interpreter { if (!results.execResult.exceptionError) { Object.assign(this._result.selfdestruct, selfdestruct) // update stateRoot on current contract - const account = await this._eei.getAccount(this._env.address) + const account = await this._stateManager.getAccount(this._env.address) if (!account) { throw new Error('could not read contract account') } @@ -897,7 +909,7 @@ export class Interpreter { } this._env.contract.nonce += BigInt(1) - await this._eei.putAccount(this._env.address, this._env.contract) + await this._stateManager.putAccount(this._env.address, this._env.contract, true) if (this._common.isActivatedEIP(3860)) { if ( @@ -942,7 +954,7 @@ export class Interpreter { ) { Object.assign(this._result.selfdestruct, selfdestruct) // update stateRoot on current contract - const account = await this._eei.getAccount(this._env.address) + const account = await this._stateManager.getAccount(this._env.address) if (!account) { throw new Error('could not read contract account') } @@ -989,15 +1001,15 @@ export class Interpreter { this._result.selfdestruct[bytesToHex(this._env.address.bytes)] = toAddress.bytes // Add to beneficiary balance - let toAccount = await this._eei.getAccount(toAddress) + let toAccount = await this._stateManager.getAccount(toAddress) if (!toAccount) { toAccount = new Account() } toAccount.balance += this._env.contract.balance - await this._eei.putAccount(toAddress, toAccount) + await this._stateManager.putAccount(toAddress, toAccount, true) // Subtract from contract balance - await this._eei.modifyAccountFields(this._env.address, { + await this._stateManager.modifyAccountFields(this._env.address, { balance: BigInt(0), }) diff --git a/packages/evm/src/opcodes/EIP2929.ts b/packages/evm/src/opcodes/EIP2929.ts index bb702ff6e6..832509c3d0 100644 --- a/packages/evm/src/opcodes/EIP2929.ts +++ b/packages/evm/src/opcodes/EIP2929.ts @@ -21,12 +21,12 @@ export function accessAddressEIP2929( ): bigint { if (common.isActivatedEIP(2929) === false) return BigInt(0) - const eei = runState.eei + const stateManager = runState.stateManager const addressStr = address.bytes // Cold - if (!eei.isWarmedAddress(addressStr)) { - eei.addWarmedAddress(addressStr) + if (!stateManager.isWarmedAddress(addressStr)) { + stateManager.addWarmedAddress(addressStr) // CREATE, CREATE2 opcodes have the address warmed for free. // selfdestruct beneficiary address reads are charged an *additional* cold access @@ -56,13 +56,13 @@ export function accessStorageEIP2929( ): bigint { if (common.isActivatedEIP(2929) === false) return BigInt(0) - const eei = runState.eei + const stateManager = runState.stateManager const address = runState.interpreter.getAddress().bytes - const slotIsCold = !eei.isWarmedStorage(address, key) + const slotIsCold = !stateManager.isWarmedStorage(address, key) // Cold (SLOAD and SSTORE) if (slotIsCold) { - eei.addWarmedStorage(address, key) + stateManager.addWarmedStorage(address, key) return common.param('gasPrices', 'coldsload') } else if (!isSstore) { return common.param('gasPrices', 'warmstorageread') @@ -89,12 +89,12 @@ export function adjustSstoreGasEIP2929( ): bigint { if (common.isActivatedEIP(2929) === false) return defaultCost - const eei = runState.eei + const stateManager = runState.stateManager const address = runState.interpreter.getAddress().bytes const warmRead = common.param('gasPrices', 'warmstorageread') const coldSload = common.param('gasPrices', 'coldsload') - if (eei.isWarmedStorage(address, key)) { + if (stateManager.isWarmedStorage(address, key)) { switch (costName) { case 'noop': return warmRead diff --git a/packages/evm/src/opcodes/functions.ts b/packages/evm/src/opcodes/functions.ts index 18a327af13..5330c86477 100644 --- a/packages/evm/src/opcodes/functions.ts +++ b/packages/evm/src/opcodes/functions.ts @@ -487,7 +487,8 @@ export const handlers: Map = new Map([ async function (runState) { const addressBigInt = runState.stack.pop() const size = BigInt( - (await runState.eei.getContractCode(new Address(addresstoBytes(addressBigInt)))).length + (await runState.stateManager.getContractCode(new Address(addresstoBytes(addressBigInt)))) + .length ) runState.stack.push(size) }, @@ -499,7 +500,9 @@ export const handlers: Map = new Map([ const [addressBigInt, memOffset, codeOffset, dataLength] = runState.stack.popN(4) if (dataLength !== BigInt(0)) { - const code = await runState.eei.getContractCode(new Address(addresstoBytes(addressBigInt))) + const code = await runState.stateManager.getContractCode( + new Address(addresstoBytes(addressBigInt)) + ) const data = getDataSlice(code, codeOffset, dataLength) const memOffsetNum = Number(memOffset) @@ -514,7 +517,7 @@ export const handlers: Map = new Map([ async function (runState) { const addressBigInt = runState.stack.pop() const address = new Address(addresstoBytes(addressBigInt)) - const account = await runState.eei.getAccount(address) + const account = await runState.stateManager.getAccount(address) if (!account || account.isEmpty()) { runState.stack.push(BigInt(0)) return @@ -569,8 +572,9 @@ export const handlers: Map = new Map([ return } - const hash = await runState.eei.getBlockHash(number) - runState.stack.push(hash) + const block = await runState.blockchain.getBlock(Number(number)) + + runState.stack.push(bytesToBigInt(block.hash())) }, ], // 0x41: COINBASE diff --git a/packages/evm/src/opcodes/gas.ts b/packages/evm/src/opcodes/gas.ts index 4601437a19..9e76de96a3 100644 --- a/packages/evm/src/opcodes/gas.ts +++ b/packages/evm/src/opcodes/gas.ts @@ -336,12 +336,12 @@ export const dynamicGasHandlers: Map BigInt(0)) { gas += common.param('gasPrices', 'authcallValueTransfer') - const account = await runState.eei.getAccount(toAddress) + const account = await runState.stateManager.getAccount(toAddress) if (!account) { gas += common.param('gasPrices', 'callNewAccount') } @@ -599,14 +599,16 @@ export const dynamicGasHandlers: Map BigInt(0)) { // This technically checks if account is empty or non-existent - const empty = await runState.eei.accountIsEmptyOrNonExistent(selfdestructToAddress) + const empty = await runState.stateManager.accountIsEmptyOrNonExistent( + selfdestructToAddress + ) if (empty) { deductGas = true } } } else if (common.gteHardfork(Hardfork.TangerineWhistle)) { // EIP-150 (Tangerine Whistle) gas semantics - const exists = await runState.eei.accountExists(selfdestructToAddress) + const exists = await runState.stateManager.accountExists(selfdestructToAddress) if (!exists) { deductGas = true } diff --git a/packages/evm/src/types.ts b/packages/evm/src/types.ts index 454ef55975..d3987582da 100644 --- a/packages/evm/src/types.ts +++ b/packages/evm/src/types.ts @@ -1,9 +1,12 @@ +import { zeros } from '@ethereumjs/util' + import type { EVM, EVMResult, ExecResult } from './evm' import type { InterpreterStep } from './interpreter' import type { Message } from './message' import type { OpHandler, OpcodeList } from './opcodes' import type { AsyncDynamicGasHandler, SyncDynamicGasHandler } from './opcodes/gas' -import type { Account, Address, AsyncEventEmitter, PrefixedHexString } from '@ethereumjs/util' +import type { EVMStateManagerInterface } from '@ethereumjs/common' +import type { Address, AsyncEventEmitter } from '@ethereumjs/util' /** * API of the EVM @@ -14,45 +17,10 @@ export interface EVMInterface { getActiveOpcodes?(): OpcodeList precompiles: Map // Note: the `any` type is used because EVM only needs to have the addresses of the precompiles (not their functions) copy(): EVMInterface - eei: EEIInterface + stateManager: EVMStateManagerInterface events?: AsyncEventEmitter } -/** - * API for an EEI (Ethereum Environment Interface) implementation - * - * This can be used to connect the EVM to different (chain) environments. - * An implementation for an EEI to connect to an Ethereum execution chain - * environment (`mainnet`, `sepolia`,...) can be found in the - * `@ethereumjs/vm` package. - */ -export interface EEIInterface extends EVMStateAccess { - getBlockHash(num: bigint): Promise - storageStore(address: Address, key: Uint8Array, value: Uint8Array): Promise - storageLoad(address: Address, key: Uint8Array, original: boolean): Promise - copy(): EEIInterface -} - -/** - * API for EVM state access, this extends the base interface from - * the `@ethereumjs/statemanager` package and is part of the broader - * EEI (see EEI interface). - * - * An implementation of this can be found in the `@ethereumjs/vm` package. - */ -export interface EVMStateAccess extends StateAccess { - addWarmedAddress(address: Uint8Array): void - isWarmedAddress(address: Uint8Array): boolean - addWarmedStorage(address: Uint8Array, slot: Uint8Array): void - isWarmedStorage(address: Uint8Array, slot: Uint8Array): boolean - clearWarmedAccounts(): void - generateAccessList?(addressesRemoved: Address[], addressesOnlyStorage: Address[]): AccessList - clearOriginalStorageCache(): void - cleanupTouchedAccounts(): Promise - generateCanonicalGenesis(initState: any): Promise - accountIsEmptyOrNonExistent(address: Address): Promise -} - export type DeleteOpcode = { opcode: number } @@ -234,51 +202,6 @@ export type EVMEvents = { */ export type Log = [address: Uint8Array, topics: Uint8Array[], data: Uint8Array] -declare type AccessListItem = { - address: PrefixedHexString - storageKeys: PrefixedHexString[] -} - -declare type AccessList = AccessListItem[] - -declare type StorageProof = { - key: PrefixedHexString - proof: PrefixedHexString[] - value: PrefixedHexString -} -declare type Proof = { - address: PrefixedHexString - balance: PrefixedHexString - codeHash: PrefixedHexString - nonce: PrefixedHexString - storageHash: PrefixedHexString - accountProof: PrefixedHexString[] - storageProof: StorageProof[] -} - -type AccountFields = Partial> - -interface StateAccess { - accountExists(address: Address): Promise - getAccount(address: Address): Promise - putAccount(address: Address, account: Account): Promise - deleteAccount(address: Address): Promise - modifyAccountFields(address: Address, accountFields: AccountFields): Promise - putContractCode(address: Address, value: Uint8Array): Promise - getContractCode(address: Address): Promise - getContractStorage(address: Address, key: Uint8Array): Promise - putContractStorage(address: Address, key: Uint8Array, value: Uint8Array): Promise - clearContractStorage(address: Address): Promise - checkpoint(): Promise - commit(): Promise - revert(): Promise - getStateRoot(): Promise - setStateRoot(stateRoot: Uint8Array, clearCache?: boolean): Promise - getProof?(address: Address, storageSlots: Uint8Array[]): Promise - verifyProof?(proof: Proof): Promise - hasStateRoot(root: Uint8Array): Promise -} - export type Block = { header: { number: bigint @@ -301,3 +224,25 @@ export interface TransientStorageInterface { toJSON(): { [address: string]: { [key: string]: string } } clear(): void } + +type MockBlock = { + hash(): Uint8Array +} + +export interface Blockchain { + getBlock(blockId: number): Promise + copy(): Blockchain +} + +export class DefaultBlockchain implements Blockchain { + async getBlock() { + return { + hash() { + return zeros(32) + }, + } + } + copy() { + return this + } +} diff --git a/packages/evm/test/asyncEvents.spec.ts b/packages/evm/test/asyncEvents.spec.ts index d6033e0a5b..a42f5ef75d 100644 --- a/packages/evm/test/asyncEvents.spec.ts +++ b/packages/evm/test/asyncEvents.spec.ts @@ -1,18 +1,18 @@ import { Chain, Common, Hardfork } from '@ethereumjs/common' +import { DefaultStateManager } from '@ethereumjs/statemanager' import { Address } from '@ethereumjs/util' import { hexToBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' import { EVM } from '../src' - -import { getEEI } from './utils' - tape('async events', async (t) => { t.plan(2) const caller = new Address(hexToBytes('00000000000000000000000000000000000000ee')) const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Constantinople }) - const eei = await getEEI() - const evm = await EVM.create({ common, eei }) + const evm = await EVM.create({ + common, + stateManager: new DefaultStateManager(), + }) evm.events.on('step', async (event, next) => { const startTime = Date.now() setTimeout(() => { diff --git a/packages/evm/test/customOpcodes.spec.ts b/packages/evm/test/customOpcodes.spec.ts index 6439c6dac3..2cebb9f1c1 100644 --- a/packages/evm/test/customOpcodes.spec.ts +++ b/packages/evm/test/customOpcodes.spec.ts @@ -1,10 +1,9 @@ +import { DefaultStateManager } from '@ethereumjs/statemanager' import { equalsBytes, hexToBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' import { EVM } from '../src/evm' -import { getEEI } from './utils' - import type { InterpreterStep, RunState } from '../src/interpreter' import type { AddOpcode } from '../src/types' @@ -29,7 +28,7 @@ tape('VM: custom opcodes', (t) => { t.test('should add custom opcodes to the EVM', async (st) => { const evm = await EVM.create({ customOpcodes: [testOpcode], - eei: await getEEI(), + stateManager: new DefaultStateManager(), }) const gas = 123456 let correctOpcodeName = false @@ -50,7 +49,7 @@ tape('VM: custom opcodes', (t) => { t.test('should delete opcodes from the EVM', async (st) => { const evm = await EVM.create({ customOpcodes: [{ opcode: 0x20 }], // deletes KECCAK opcode - eei: await getEEI(), + stateManager: new DefaultStateManager(), }) const gas = BigInt(123456) const res = await evm.runCode({ @@ -65,7 +64,7 @@ tape('VM: custom opcodes', (t) => { // Thus, each time you recreate a EVM, it is in a clean state const evm = await EVM.create({ customOpcodes: [{ opcode: 0x01 }], // deletes ADD opcode - eei: await getEEI(), + stateManager: new DefaultStateManager(), }) const gas = BigInt(123456) const res = await evm.runCode({ @@ -74,8 +73,9 @@ tape('VM: custom opcodes', (t) => { }) st.ok(res.executionGasUsed === gas, 'successfully deleted opcode') - const eei = await getEEI() - const evmDefault = await EVM.create({ eei }) + const evmDefault = await EVM.create({ + stateManager: new DefaultStateManager(), + }) // PUSH 04 // PUSH 01 @@ -96,7 +96,7 @@ tape('VM: custom opcodes', (t) => { testOpcode.opcode = 0x20 // Overrides KECCAK const evm = await EVM.create({ customOpcodes: [testOpcode], - eei: await getEEI(), + stateManager: new DefaultStateManager(), }) const gas = 123456 const res = await evm.runCode({ @@ -122,7 +122,7 @@ tape('VM: custom opcodes', (t) => { const evm = await EVM.create({ customOpcodes: [testOpcode], - eei: await getEEI(), + stateManager: new DefaultStateManager(), }) const evmCopy = evm.copy() diff --git a/packages/evm/test/customPrecompiles.spec.ts b/packages/evm/test/customPrecompiles.spec.ts index ba6af03d9e..8193783c56 100644 --- a/packages/evm/test/customPrecompiles.spec.ts +++ b/packages/evm/test/customPrecompiles.spec.ts @@ -1,11 +1,10 @@ +import { DefaultStateManager } from '@ethereumjs/statemanager' import { Address } from '@ethereumjs/util' import { hexToBytes, utf8ToBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' import { EVM } from '../src/evm' -import { getEEI } from './utils' - import type { ExecResult } from '../src/evm' import type { PrecompileInput } from '../src/precompiles' @@ -31,7 +30,7 @@ tape('EVM -> custom precompiles', (t) => { function: customPrecompile, }, ], - eei: await getEEI(), + stateManager: new DefaultStateManager(), }) const result = await EVMOverride.runCall({ to: shaAddress, @@ -51,7 +50,7 @@ tape('EVM -> custom precompiles', (t) => { address: shaAddress, }, ], - eei: await getEEI(), + stateManager: new DefaultStateManager(), }) const result = await EVMOverride.runCall({ to: shaAddress, @@ -71,7 +70,7 @@ tape('EVM -> custom precompiles', (t) => { function: customPrecompile, }, ], - eei: await getEEI(), + stateManager: new DefaultStateManager(), }) const result = await EVMOverride.runCall({ to: newPrecompile, @@ -84,7 +83,9 @@ tape('EVM -> custom precompiles', (t) => { }) t.test('should not persist changes to precompiles', async (st) => { - let EVMSha = await EVM.create({ eei: await getEEI() }) + let EVMSha = await EVM.create({ + stateManager: new DefaultStateManager(), + }) const shaResult = await EVMSha.runCall({ to: shaAddress, gasLimit: BigInt(30000), @@ -98,7 +99,7 @@ tape('EVM -> custom precompiles', (t) => { function: customPrecompile, }, ], - eei: await getEEI(), + stateManager: new DefaultStateManager(), }) const result = await EVMOverride.runCall({ to: shaAddress, @@ -107,9 +108,11 @@ tape('EVM -> custom precompiles', (t) => { caller: sender, }) // sanity: check we have overridden - st.deepEquals(result.execResult.returnValue, expectedReturn, 'return value is correct') - st.equals(result.execResult.executionGasUsed, expectedGas, 'gas used is correct') - EVMSha = await EVM.create({ eei: await getEEI() }) + st.deepEqual(result.execResult.returnValue, expectedReturn, 'return value is correct') + st.ok(result.execResult.executionGasUsed === expectedGas, 'gas used is correct') + EVMSha = await EVM.create({ + stateManager: new DefaultStateManager(), + }) const shaResult2 = await EVMSha.runCall({ to: shaAddress, gasLimit: BigInt(30000), @@ -135,7 +138,7 @@ tape('EVM -> custom precompiles', (t) => { function: customPrecompile, }, ], - eei: await getEEI(), + stateManager: new DefaultStateManager(), }) const evmCopy = evm.copy() st.deepEqual( diff --git a/packages/evm/test/eips/eip-3860.spec.ts b/packages/evm/test/eips/eip-3860.spec.ts index cf2fd84457..765d72009f 100644 --- a/packages/evm/test/eips/eip-3860.spec.ts +++ b/packages/evm/test/eips/eip-3860.spec.ts @@ -1,10 +1,10 @@ import { Chain, Common, Hardfork } from '@ethereumjs/common' +import { DefaultStateManager } from '@ethereumjs/statemanager' import { Address, concatBytesNoTypeCheck, privateToAddress } from '@ethereumjs/util' import { concatBytes, equalsBytes, hexToBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' import { EVM } from '../../src' -import { getEEI } from '../utils' const pkey = hexToBytes('20'.repeat(32)) const sender = new Address(privateToAddress(pkey)) @@ -16,8 +16,10 @@ tape('EIP 3860 tests', (t) => { hardfork: Hardfork.London, eips: [3860], }) - const eei = await getEEI() - const evm = await EVM.create({ common, eei }) + const evm = await EVM.create({ + common, + stateManager: new DefaultStateManager(), + }) const buffer = new Uint8Array(1000000).fill(0x60) @@ -55,19 +57,24 @@ tape('EIP 3860 tests', (t) => { eips: [], }) const caller = Address.fromString('0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b') - const eei = await getEEI() - const evm = await EVM.create({ common: commonWith3860, eei }) - const evmWithout3860 = await EVM.create({ common: commonWithout3860, eei: eei.copy() }) + const evm = await EVM.create({ + common: commonWith3860, + stateManager: new DefaultStateManager(), + }) + const evmWithout3860 = await EVM.create({ + common: commonWithout3860, + stateManager: new DefaultStateManager(), + }) const contractFactory = Address.fromString('0xb94f5374fce5edbc8e2a8697c15331677e6ebf0b') - const contractAccount = await evm.eei.getAccount(contractFactory) - await evm.eei.putAccount(contractFactory, contractAccount!) - await evmWithout3860.eei.putAccount(contractFactory, contractAccount!) + const contractAccount = await evm.stateManager.getAccount(contractFactory) + await evm.stateManager.putAccount(contractFactory, contractAccount!) + await evmWithout3860.stateManager.putAccount(contractFactory, contractAccount!) const factoryCode = hexToBytes( '7f600a80600080396000f3000000000000000000000000000000000000000000006000526000355a8160006000f05a8203600a55806000556001600155505050' ) - await evm.eei.putContractCode(contractFactory, factoryCode) - await evmWithout3860.eei.putContractCode(contractFactory, factoryCode) + await evm.stateManager.putContractCode(contractFactory, factoryCode) + await evmWithout3860.stateManager.putContractCode(contractFactory, factoryCode) const data = hexToBytes('000000000000000000000000000000000000000000000000000000000000c000') const runCallArgs = { from: caller, @@ -97,19 +104,24 @@ tape('EIP 3860 tests', (t) => { eips: [], }) const caller = Address.fromString('0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b') - const eei = await getEEI() - const evm = await EVM.create({ common: commonWith3860, eei }) - const evmWithout3860 = await EVM.create({ common: commonWithout3860, eei: eei.copy() }) + const evm = await EVM.create({ + common: commonWith3860, + stateManager: new DefaultStateManager(), + }) + const evmWithout3860 = await EVM.create({ + common: commonWithout3860, + stateManager: new DefaultStateManager(), + }) const contractFactory = Address.fromString('0xb94f5374fce5edbc8e2a8697c15331677e6ebf0b') - const contractAccount = await evm.eei.getAccount(contractFactory) - await evm.eei.putAccount(contractFactory, contractAccount!) - await evmWithout3860.eei.putAccount(contractFactory, contractAccount!) + const contractAccount = await evm.stateManager.getAccount(contractFactory) + await evm.stateManager.putAccount(contractFactory, contractAccount!) + await evmWithout3860.stateManager.putAccount(contractFactory, contractAccount!) const factoryCode = hexToBytes( '7f600a80600080396000f3000000000000000000000000000000000000000000006000526000355a60008260006000f55a8203600a55806000556001600155505050' ) - await evm.eei.putContractCode(contractFactory, factoryCode) - await evmWithout3860.eei.putContractCode(contractFactory, factoryCode) + await evm.stateManager.putContractCode(contractFactory, factoryCode) + await evmWithout3860.stateManager.putContractCode(contractFactory, factoryCode) const data = hexToBytes('000000000000000000000000000000000000000000000000000000000000c000') const runCallArgs = { from: caller, @@ -132,8 +144,12 @@ tape('EIP 3860 tests', (t) => { hardfork: Hardfork.London, eips: [3860], }) - const eei = await getEEI() - const evm = await EVM.create({ common, eei, allowUnlimitedInitCodeSize: true }) + const evm = await EVM.create({ + common, + stateManager: new DefaultStateManager(), + + allowUnlimitedInitCodeSize: true, + }) const bytes = new Uint8Array(1000000).fill(0x60) @@ -164,21 +180,22 @@ tape('EIP 3860 tests', (t) => { }) const caller = Address.fromString('0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b') for (const code of ['F0', 'F5']) { - const eei = await getEEI() const evm = await EVM.create({ common: commonWith3860, - eei, + stateManager: new DefaultStateManager(), + allowUnlimitedInitCodeSize: true, }) const evmDisabled = await EVM.create({ common: commonWith3860, - eei: eei.copy(), + stateManager: new DefaultStateManager(), + allowUnlimitedInitCodeSize: false, }) const contractFactory = Address.fromString('0xb94f5374fce5edbc8e2a8697c15331677e6ebf0b') - const contractAccount = await evm.eei.getAccount(contractFactory) - await evm.eei.putAccount(contractFactory, contractAccount!) - await evmDisabled.eei.putAccount(contractFactory, contractAccount!) + const contractAccount = await evm.stateManager.getAccount(contractFactory) + await evm.stateManager.putAccount(contractFactory, contractAccount!) + await evmDisabled.stateManager.putAccount(contractFactory, contractAccount!) // This factory code: // -> reads 32 bytes from the calldata (X) // Attempts to create a contract of X size @@ -187,8 +204,8 @@ tape('EIP 3860 tests', (t) => { // This is either the contract address if it was succesful, or 0 in case of error const factoryCode = hexToBytes('600060003560006000' + code + '600055') - await evm.eei.putContractCode(contractFactory, factoryCode) - await evmDisabled.eei.putContractCode(contractFactory, factoryCode) + await evm.stateManager.putContractCode(contractFactory, factoryCode) + await evmDisabled.stateManager.putContractCode(contractFactory, factoryCode) const runCallArgs = { from: caller, @@ -201,8 +218,11 @@ tape('EIP 3860 tests', (t) => { await evmDisabled.runCall(runCallArgs) const key0 = hexToBytes('00'.repeat(32)) - const storageActive = await evm.eei.getContractStorage(contractFactory, key0) - const storageInactive = await evmDisabled.eei.getContractStorage(contractFactory, key0) + const storageActive = await evm.stateManager.getContractStorage(contractFactory, key0) + const storageInactive = await evmDisabled.stateManager.getContractStorage( + contractFactory, + key0 + ) st.ok( !equalsBytes(storageActive, new Uint8Array()), diff --git a/packages/evm/test/opcodes.spec.ts b/packages/evm/test/opcodes.spec.ts index 9496257f31..24fa67c6bc 100644 --- a/packages/evm/test/opcodes.spec.ts +++ b/packages/evm/test/opcodes.spec.ts @@ -1,17 +1,19 @@ import { Chain, Common, Hardfork } from '@ethereumjs/common' +import { DefaultStateManager } from '@ethereumjs/statemanager' import * as tape from 'tape' import { EVM } from '../src' -import { getEEI } from './utils' - tape('EVM -> getActiveOpcodes()', (t) => { const CHAINID = 0x46 //istanbul opcode const BEGINSUB = 0x5c // EIP-2315 opcode t.test('should not expose opcodes from a follow-up HF (istanbul -> petersburg)', async (st) => { const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Petersburg }) - const evm = await EVM.create({ common, eei: await getEEI() }) + const evm = await EVM.create({ + common, + stateManager: new DefaultStateManager(), + }) st.equal( evm.getActiveOpcodes().get(CHAINID), undefined, @@ -22,7 +24,10 @@ tape('EVM -> getActiveOpcodes()', (t) => { t.test('should expose opcodes when HF is active (>= istanbul)', async (st) => { let common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Istanbul }) - let evm = await EVM.create({ common, eei: await getEEI() }) + let evm = await EVM.create({ + common, + stateManager: new DefaultStateManager(), + }) st.equal( evm.getActiveOpcodes().get(CHAINID)!.name, 'CHAINID', @@ -30,7 +35,10 @@ tape('EVM -> getActiveOpcodes()', (t) => { ) common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.MuirGlacier }) - evm = await EVM.create({ common, eei: await getEEI() }) + evm = await EVM.create({ + common, + stateManager: new DefaultStateManager(), + }) st.equal( evm.getActiveOpcodes().get(CHAINID)!.name, 'CHAINID', @@ -42,7 +50,10 @@ tape('EVM -> getActiveOpcodes()', (t) => { t.test('should expose opcodes when EIP is active', async (st) => { let common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Istanbul, eips: [2315] }) - let evm = await EVM.create({ common, eei: await getEEI() }) + let evm = await EVM.create({ + common, + stateManager: new DefaultStateManager(), + }) st.equal( evm.getActiveOpcodes().get(BEGINSUB)!.name, 'BEGINSUB', @@ -50,7 +61,10 @@ tape('EVM -> getActiveOpcodes()', (t) => { ) common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Istanbul }) - evm = await EVM.create({ common, eei: await getEEI() }) + evm = await EVM.create({ + common, + stateManager: new DefaultStateManager(), + }) st.equal( evm.getActiveOpcodes().get(BEGINSUB), undefined, @@ -62,7 +76,10 @@ tape('EVM -> getActiveOpcodes()', (t) => { t.test('should update opcodes on a hardfork change', async (st) => { const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Istanbul }) - const evm = await EVM.create({ common, eei: await getEEI() }) + const evm = await EVM.create({ + common, + stateManager: new DefaultStateManager(), + }) common.setHardfork(Hardfork.Byzantium) st.equal( diff --git a/packages/evm/test/precompiles/06-ecadd.spec.ts b/packages/evm/test/precompiles/06-ecadd.spec.ts index 113d5db14c..a79a794863 100644 --- a/packages/evm/test/precompiles/06-ecadd.spec.ts +++ b/packages/evm/test/precompiles/06-ecadd.spec.ts @@ -1,15 +1,17 @@ import { Chain, Common, Hardfork } from '@ethereumjs/common' +import { DefaultStateManager } from '@ethereumjs/statemanager' import * as tape from 'tape' import { EVM } from '../../src' import { getActivePrecompiles } from '../../src/precompiles' -import { getEEI } from '../utils' tape('Precompiles: ECADD', (t) => { t.test('ECADD', async (st) => { const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Petersburg }) - const eei = await getEEI() - const evm = await EVM.create({ common, eei }) + const evm = await EVM.create({ + common, + stateManager: new DefaultStateManager(), + }) const addressStr = '0000000000000000000000000000000000000006' const ECADD = getActivePrecompiles(common).get(addressStr)! diff --git a/packages/evm/test/precompiles/07-ecmul.spec.ts b/packages/evm/test/precompiles/07-ecmul.spec.ts index 73f57ee4de..c26b2c7957 100644 --- a/packages/evm/test/precompiles/07-ecmul.spec.ts +++ b/packages/evm/test/precompiles/07-ecmul.spec.ts @@ -1,15 +1,17 @@ import { Chain, Common, Hardfork } from '@ethereumjs/common' +import { DefaultStateManager } from '@ethereumjs/statemanager' import * as tape from 'tape' import { EVM } from '../../src' import { getActivePrecompiles } from '../../src/precompiles' -import { getEEI } from '../utils' tape('Precompiles: ECMUL', (t) => { t.test('ECMUL', async (st) => { const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Petersburg }) - const eei = await getEEI() - const evm = await EVM.create({ common, eei }) + const evm = await EVM.create({ + common, + stateManager: new DefaultStateManager(), + }) const ECMUL = getActivePrecompiles(common).get('0000000000000000000000000000000000000007')! const result = await ECMUL({ diff --git a/packages/evm/test/precompiles/08-ecpairing.spec.ts b/packages/evm/test/precompiles/08-ecpairing.spec.ts index 95e96c4d0e..e5230f39dc 100644 --- a/packages/evm/test/precompiles/08-ecpairing.spec.ts +++ b/packages/evm/test/precompiles/08-ecpairing.spec.ts @@ -1,16 +1,18 @@ import { Chain, Common, Hardfork } from '@ethereumjs/common' +import { DefaultStateManager } from '@ethereumjs/statemanager' import { hexToBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' import { EVM } from '../../src' import { getActivePrecompiles } from '../../src/precompiles' -import { getEEI } from '../utils' tape('Precompiles: ECPAIRING', (t) => { t.test('ECPAIRING', async (st) => { const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Petersburg }) - const eei = await getEEI() - const evm = await EVM.create({ common, eei }) + const evm = await EVM.create({ + common, + stateManager: new DefaultStateManager(), + }) const addressStr = '0000000000000000000000000000000000000008' const ECPAIRING = getActivePrecompiles(common).get(addressStr)! const result = await ECPAIRING({ diff --git a/packages/evm/test/precompiles/14-pointevaluation.spec.ts b/packages/evm/test/precompiles/14-pointevaluation.spec.ts index b625a90f0b..06424ec44f 100644 --- a/packages/evm/test/precompiles/14-pointevaluation.spec.ts +++ b/packages/evm/test/precompiles/14-pointevaluation.spec.ts @@ -1,4 +1,5 @@ import { Common, Hardfork } from '@ethereumjs/common' +import { DefaultStateManager } from '@ethereumjs/statemanager' import { bigIntToBytes, bytesToBigInt, @@ -13,7 +14,6 @@ import * as tape from 'tape' import { EVM, getActivePrecompiles } from '../../src' import { BLS_MODULUS } from '../../src/precompiles/14-kzg-point-evaluation' -import { getEEI } from '../utils' import type { PrecompileInput } from '../../src/precompiles' @@ -25,8 +25,10 @@ tape('Precompiles: point evaluation', async (t) => { chain: 'custom', hardfork: Hardfork.Cancun, }) - const eei = await getEEI() - const evm = await EVM.create({ common, eei }) + const evm = await EVM.create({ + common, + stateManager: new DefaultStateManager(), + }) const addressStr = '0000000000000000000000000000000000000014' const pointEvaluation = getActivePrecompiles(common).get(addressStr)! diff --git a/packages/evm/test/precompiles/eip-2537-BLS.spec.ts b/packages/evm/test/precompiles/eip-2537-BLS.spec.ts index dc8b3c5030..b272c282d5 100644 --- a/packages/evm/test/precompiles/eip-2537-BLS.spec.ts +++ b/packages/evm/test/precompiles/eip-2537-BLS.spec.ts @@ -1,4 +1,5 @@ import { Chain, Common, Hardfork } from '@ethereumjs/common' +import { DefaultStateManager } from '@ethereumjs/statemanager' import { Address, bytesToPrefixedHexString } from '@ethereumjs/util' import { hexToBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' @@ -6,7 +7,6 @@ import * as tape from 'tape' import { isRunningInKarma } from '../../../vm/test/util' import { getActivePrecompiles } from '../../src' import { EVM } from '../../src/evm' -import { getEEI } from '../utils' const precompileAddressStart = 0x0a const precompileAddressEnd = 0x12 @@ -24,8 +24,10 @@ tape('EIP-2537 BLS tests', (t) => { return st.end() } const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.MuirGlacier }) - const eei = await getEEI() - const evm = await EVM.create({ common, eei }) + const evm = await EVM.create({ + common, + stateManager: new DefaultStateManager(), + }) for (const address of precompiles) { const to = new Address(hexToBytes(address)) @@ -56,8 +58,10 @@ tape('EIP-2537 BLS tests', (t) => { return st.end() } const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Byzantium, eips: [2537] }) - const eei = await getEEI() - const evm = await EVM.create({ common, eei }) + const evm = await EVM.create({ + common, + stateManager: new DefaultStateManager(), + }) for (const address of precompiles) { const to = new Address(hexToBytes(address)) @@ -95,8 +99,10 @@ tape('EIP-2537 BLS tests', (t) => { return st.end() } const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Berlin, eips: [2537] }) - const eei = await getEEI() - const evm = await EVM.create({ common, eei }) + const evm = await EVM.create({ + common, + stateManager: new DefaultStateManager(), + }) const BLS12G2MultiExp = getActivePrecompiles(common).get( '000000000000000000000000000000000000000f' )! diff --git a/packages/evm/test/precompiles/hardfork.spec.ts b/packages/evm/test/precompiles/hardfork.spec.ts index 0ec4ce680a..be96eb058a 100644 --- a/packages/evm/test/precompiles/hardfork.spec.ts +++ b/packages/evm/test/precompiles/hardfork.spec.ts @@ -1,11 +1,11 @@ import { Chain, Common, Hardfork } from '@ethereumjs/common' +import { DefaultStateManager } from '@ethereumjs/statemanager' import { Address } from '@ethereumjs/util' import { hexToBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' import { EVM } from '../../src' import { getActivePrecompiles } from '../../src/precompiles' -import { getEEI } from '../utils' tape('Precompiles: hardfork availability', (t) => { t.test('Test ECPAIRING availability', async (st) => { @@ -23,8 +23,10 @@ tape('Precompiles: hardfork availability', (t) => { st.pass('ECPAIRING available in petersburg') } - const eeiByzantium = await getEEI() - let evm = await EVM.create({ common: commonByzantium, eei: eeiByzantium }) + let evm = await EVM.create({ + common: commonByzantium, + stateManager: new DefaultStateManager(), + }) let result = await evm.runCall({ caller: Address.zero(), gasLimit: BigInt(0xffffffffff), @@ -43,8 +45,10 @@ tape('Precompiles: hardfork availability', (t) => { st.pass('ECPAIRING available in petersburg') } - const eeiPetersburg = await getEEI() - evm = await EVM.create({ common: commonPetersburg, eei: eeiPetersburg }) + evm = await EVM.create({ + common: commonPetersburg, + stateManager: new DefaultStateManager(), + }) result = await evm.runCall({ caller: Address.zero(), gasLimit: BigInt(0xffffffffff), @@ -64,8 +68,10 @@ tape('Precompiles: hardfork availability', (t) => { st.pass('ECPAIRING not available in homestead') } - const eeiHomestead = await getEEI() - evm = await EVM.create({ common: commonHomestead, eei: eeiHomestead }) + evm = await EVM.create({ + common: commonHomestead, + stateManager: new DefaultStateManager(), + }) result = await evm.runCall({ caller: Address.zero(), diff --git a/packages/evm/test/runCall.spec.ts b/packages/evm/test/runCall.spec.ts index ecf470db0e..b2bd9c3886 100644 --- a/packages/evm/test/runCall.spec.ts +++ b/packages/evm/test/runCall.spec.ts @@ -1,4 +1,5 @@ import { Chain, Common, Hardfork } from '@ethereumjs/common' +import { DefaultStateManager } from '@ethereumjs/statemanager' import { Account, Address, @@ -14,8 +15,6 @@ import * as tape from 'tape' import { EVM } from '../src' import { ERROR } from '../src/exceptions' -import { getEEI } from './utils' - import type { EVMRunCallOpts } from '../src/types' // Non-protected Create2Address generator. Does not check if Uint8Arrays have the right padding. @@ -27,8 +26,10 @@ function create2address(sourceAddress: Address, codeHash: Uint8Array, salt: Uint tape('Create where FROM account nonce is 0', async (t) => { const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Constantinople }) - const eei = await getEEI() - const evm = await EVM.create({ common, eei }) + const evm = await EVM.create({ + common, + stateManager: new DefaultStateManager(), + }) const res = await evm.runCall({ to: undefined }) t.equals( res.createdAddress?.toString(), @@ -52,8 +53,10 @@ tape('Constantinople: EIP-1014 CREATE2 creates the right contract address', asyn const contractAddress = new Address(hexToBytes('00000000000000000000000000000000000000ff')) // contract address // setup the vm const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Constantinople }) - const eei = await getEEI() - const evm = await EVM.create({ common, eei }) + const evm = await EVM.create({ + common, + stateManager: new DefaultStateManager(), + }) const code = '3460008080F560005260206000F3' /* code: remarks: (top of the stack is at the zero index) @@ -69,9 +72,9 @@ tape('Constantinople: EIP-1014 CREATE2 creates the right contract address', asyn RETURN [0x00, 0x20] */ - await eei.putContractCode(contractAddress, hexToBytes(code)) // setup the contract code - await eei.putAccount(caller, new Account(BigInt(0), BigInt(0x11111111))) // give the calling account a big balance so we don't run out of funds - const codeHash = keccak256(hexToBytes('')) + await evm.stateManager.putContractCode(contractAddress, hexToBytes(code)) // setup the contract code + await evm.stateManager.putAccount(caller, new Account(BigInt(0), BigInt(0x11111111))) // give the calling account a big balance so we don't run out of funds + const codeHash = keccak256(new Uint8Array()) for (let value = 0; value <= 1000; value += 20) { // setup the call arguments const runCallArgs = { @@ -110,15 +113,13 @@ tape('Byzantium cannot access Constantinople opcodes', async (t) => { const caller = new Address(hexToBytes('00000000000000000000000000000000000000ee')) // caller address const contractAddress = new Address(hexToBytes('00000000000000000000000000000000000000ff')) // contract address // setup the evm - const eeiByzantium = await getEEI() - const eeiConstantinople = await getEEI() const evmByzantium = await EVM.create({ common: new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Byzantium }), - eei: eeiByzantium, + stateManager: new DefaultStateManager(), }) const evmConstantinople = await EVM.create({ common: new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Constantinople }), - eei: eeiConstantinople, + stateManager: new DefaultStateManager(), }) const code = '600160011B00' /* @@ -129,8 +130,8 @@ tape('Byzantium cannot access Constantinople opcodes', async (t) => { STOP */ - await eeiByzantium.putContractCode(contractAddress, hexToBytes(code)) // setup the contract code - await eeiConstantinople.putContractCode(contractAddress, hexToBytes(code)) // setup the contract code + await evmByzantium.stateManager.putContractCode(contractAddress, hexToBytes(code)) // setup the contract code + await evmConstantinople.stateManager.putContractCode(contractAddress, hexToBytes(code)) // setup the contract code const runCallArgs = { caller, // call address @@ -160,8 +161,10 @@ tape('Ensure that Istanbul sstoreCleanRefundEIP2200 gas is applied correctly', a const address = new Address(hexToBytes('00000000000000000000000000000000000000ff')) // setup the vm const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Istanbul }) - const eei = await getEEI() - const evm = await EVM.create({ common, eei }) + const evm = await EVM.create({ + common, + stateManager: new DefaultStateManager(), + }) const code = '61000260005561000160005500' /* idea: store the original value in the storage slot, except it is now a 1-length Uint8Array instead of a 32-length Uint8Array @@ -184,8 +187,12 @@ tape('Ensure that Istanbul sstoreCleanRefundEIP2200 gas is applied correctly', a */ - await eei.putContractCode(address, hexToBytes(code)) - await eei.putContractStorage(address, new Uint8Array(32), hexToBytes('00'.repeat(31) + '01')) + await evm.stateManager.putContractCode(address, hexToBytes(code)) + await evm.stateManager.putContractStorage( + address, + new Uint8Array(32), + hexToBytes('00'.repeat(31) + '01') + ) // setup the call arguments const runCallArgs = { @@ -208,12 +215,14 @@ tape('ensure correct gas for pre-constantinople sstore', async (t) => { const address = new Address(hexToBytes('00000000000000000000000000000000000000ff')) // setup the vm const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Chainstart }) - const eei = await getEEI() - const evm = await EVM.create({ common, eei }) + const evm = await EVM.create({ + common, + stateManager: new DefaultStateManager(), + }) // push 1 push 0 sstore stop const code = '600160015500' - await eei.putContractCode(address, hexToBytes(code)) + await evm.stateManager.putContractCode(address, hexToBytes(code)) // setup the call arguments const runCallArgs = { @@ -236,12 +245,14 @@ tape('ensure correct gas for calling non-existent accounts in homestead', async const address = new Address(hexToBytes('00000000000000000000000000000000000000ff')) // setup the vm const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Homestead }) - const eei = await getEEI() - const evm = await EVM.create({ common, eei }) + const evm = await EVM.create({ + common, + stateManager: new DefaultStateManager(), + }) // code to call 0x00..00dd, which does not exist const code = '6000600060006000600060DD61FFFF5A03F100' - await eei.putContractCode(address, hexToBytes(code)) + await evm.stateManager.putContractCode(address, hexToBytes(code)) // setup the call arguments const runCallArgs = { @@ -268,13 +279,15 @@ tape( const address = new Address(hexToBytes('00000000000000000000000000000000000000ff')) // setup the vm const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Homestead }) - const eei = await getEEI() - const evm = await EVM.create({ common, eei }) + const evm = await EVM.create({ + common, + stateManager: new DefaultStateManager(), + }) // code to call back into the calling account (0x00..00EE), // but using too much memory const code = '61FFFF60FF60006000600060EE6000F200' - await eei.putContractCode(address, hexToBytes(code)) + await evm.stateManager.putContractCode(address, hexToBytes(code)) // setup the call arguments const runCallArgs = { @@ -299,14 +312,16 @@ tape('ensure selfdestruct pays for creating new accounts', async (t) => { const address = new Address(hexToBytes('00000000000000000000000000000000000000ff')) // setup the vm const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.TangerineWhistle }) - const eei = await getEEI() - const evm = await EVM.create({ common, eei }) + const evm = await EVM.create({ + common, + stateManager: new DefaultStateManager(), + }) // code to call 0x00..00fe, with the GAS opcode used as gas // this cannot be paid, since we also have to pay for CALL (40 gas) // this should thus go OOG const code = '60FEFF' - await eei.putContractCode(address, hexToBytes(code)) + await evm.stateManager.putContractCode(address, hexToBytes(code)) // setup the call arguments const runCallArgs = { @@ -330,19 +345,21 @@ tape('ensure that sstores pay for the right gas costs pre-byzantium', async (t) const address = new Address(hexToBytes('00000000000000000000000000000000000000ff')) // setup the vm const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Chainstart }) - const eei = await getEEI() - const evm = await EVM.create({ common, eei }) + const evm = await EVM.create({ + common, + stateManager: new DefaultStateManager(), + }) // code to call 0x00..00fe, with the GAS opcode used as gas // this cannot be paid, since we also have to pay for CALL (40 gas) // this should thus go OOG const code = '3460005500' - await eei.putAccount(caller, new Account()) - await eei.putContractCode(address, hexToBytes(code)) + await evm.stateManager.putAccount(caller, new Account()) + await evm.stateManager.putContractCode(address, hexToBytes(code)) - const account = await eei.getAccount(caller) + const account = await evm.stateManager.getAccount(caller) account!.balance = BigInt(100) - await eei.putAccount(caller, account!) + await evm.stateManager.putAccount(caller, account!) /* Situation: @@ -402,8 +419,10 @@ tape( const emptyBytes = hexToBytes('') // setup the vm const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.London }) - const eei = await getEEI() - const evm = await EVM.create({ common, eei }) + const evm = await EVM.create({ + common, + stateManager: new DefaultStateManager(), + }) const code = '60008080F060005500' /* This simple code tries to create an empty contract and then stores the address of the contract in the zero slot. @@ -417,11 +436,11 @@ tape( STOP */ - await eei.putContractCode(address, hexToBytes(code)) + await evm.stateManager.putContractCode(address, hexToBytes(code)) - const account = await eei.getAccount(address) + const account = await evm.stateManager.getAccount(address) account!.nonce = MAX_UINT64 - BigInt(1) - await eei.putAccount(address, account!) + await evm.stateManager.putAccount(address, account!) // setup the call arguments const runCallArgs = { @@ -431,7 +450,7 @@ tape( } await evm.runCall(runCallArgs) - let storage = await eei.getContractStorage(address, slot) + let storage = await evm.stateManager.getContractStorage(address, slot) // The nonce is MAX_UINT64 - 1, so we are allowed to create a contract (nonce of creating contract is now MAX_UINT64) t.notDeepEqual(storage, emptyBytes, 'successfully created contract') @@ -439,7 +458,7 @@ tape( await evm.runCall(runCallArgs) // The nonce is MAX_UINT64, so we are NOT allowed to create a contract (nonce of creating contract is now MAX_UINT64) - storage = await eei.getContractStorage(address, slot) + storage = await evm.stateManager.getContractStorage(address, slot) t.deepEquals( storage, emptyBytes, @@ -458,14 +477,16 @@ tape('Ensure that IDENTITY precompile copies the memory', async (t) => { const caller = new Address(hexToBytes('1a02a619e51cc5f8a2a61d2a60f6c80476ee8ead')) // caller address // setup the vm const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.London }) - const eei = await getEEI() - const evm = await EVM.create({ common, eei }) + const evm = await EVM.create({ + common, + stateManager: new DefaultStateManager(), + }) const code = '3034526020600760203460045afa602034343e604034f3' const account = new Account() account!.nonce = BigInt(1) // ensure nonce for contract is correct account!.balance = BigInt(10000000000000000) - await eei.putAccount(caller, account!) + await evm.stateManager.putAccount(caller, account!) // setup the call arguments const runCallArgs = { @@ -481,7 +502,7 @@ tape('Ensure that IDENTITY precompile copies the memory', async (t) => { '00000000000000000000000028373a29d17af317e669579d97e7dddc9da6e3e2e7dddc9da6e3e200000000000000000000000000000000000000000000000000' t.equals(result.createdAddress?.toString(), expectedAddress, 'created address correct') - const deployedCode = await eei.getContractCode(result.createdAddress!) + const deployedCode = await evm.stateManager.getContractCode(result.createdAddress!) t.equals(bytesToHex(deployedCode), expectedCode, 'deployed code correct') t.end() @@ -490,8 +511,10 @@ tape('Ensure that IDENTITY precompile copies the memory', async (t) => { tape('Throws on negative call value', async (t) => { // setup the vm const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Istanbul }) - const eei = await getEEI() - const evm = await EVM.create({ common, eei }) + const evm = await EVM.create({ + common, + stateManager: new DefaultStateManager(), + }) // setup the call arguments const runCallArgs = { @@ -512,13 +535,15 @@ tape('Throws on negative call value', async (t) => { tape('runCall() -> skipBalance behavior', async (t) => { t.plan(7) const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Berlin }) - const eei = await getEEI() - const evm = await EVM.create({ common, eei }) + const evm = await EVM.create({ + common, + stateManager: new DefaultStateManager(), + }) // runCall against a contract to reach `_reduceSenderBalance` const contractCode = hexToBytes('00') // 00: STOP const contractAddress = Address.fromString('0x000000000000000000000000636F6E7472616374') - await eei.putContractCode(contractAddress, contractCode) + await evm.stateManager.putContractCode(contractAddress, contractCode) const senderKey = hexToBytes('e331b6d69882b4cb4ea581d88e0b604039a3de5967688d3dcffdd2270c0fd109') const sender = Address.fromPrivateKey(senderKey) @@ -531,10 +556,10 @@ tape('runCall() -> skipBalance behavior', async (t) => { } for (const balance of [undefined, BigInt(5)]) { - await eei.modifyAccountFields(sender, { nonce: BigInt(0), balance }) + await evm.stateManager.modifyAccountFields(sender, { nonce: BigInt(0), balance }) const res = await evm.runCall(runCallArgs) t.pass('runCall should not throw with no balance and skipBalance') - const senderBalance = (await eei.getAccount(sender))!.balance + const senderBalance = (await evm.stateManager.getAccount(sender))!.balance t.equal( senderBalance, balance ?? BigInt(0), @@ -556,8 +581,10 @@ tape('runCall() => allows to detect for max code size deposit errors', async (t) const caller = new Address(hexToBytes('00000000000000000000000000000000000000ee')) // caller address // setup the evm const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Istanbul }) - const eei = await getEEI() - const evm = await EVM.create({ common, eei }) + const evm = await EVM.create({ + common, + stateManager: new DefaultStateManager(), + }) // setup the call arguments const runCallArgs = { @@ -583,8 +610,10 @@ tape('runCall() => use DATAHASH opcode from EIP 4844', async (t) => { chain: 'custom', hardfork: Hardfork.Cancun, }) - const eei = await getEEI() - const evm = await EVM.create({ common, eei }) + const evm = await EVM.create({ + common, + stateManager: new DefaultStateManager(), + }) // setup the call arguments const runCallArgs: EVMRunCallOpts = { @@ -619,12 +648,14 @@ tape('runCall() => use DATAHASH opcode from EIP 4844', async (t) => { tape('step event: ensure EVM memory and not internal memory gets reported', async (t) => { t.plan(5) const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Berlin }) - const eei = await getEEI() - const evm = await EVM.create({ common, eei }) + const evm = await EVM.create({ + common, + stateManager: new DefaultStateManager(), + }) const contractCode = hexToBytes('600060405200') // PUSH 0 PUSH 40 MSTORE STOP const contractAddress = Address.fromString('0x000000000000000000000000636F6E7472616374') - await eei.putContractCode(contractAddress, contractCode) + await evm.stateManager.putContractCode(contractAddress, contractCode) const runCallArgs = { gasLimit: BigInt(21000), diff --git a/packages/evm/test/runCode.spec.ts b/packages/evm/test/runCode.spec.ts index 60fb632396..b5ca8d0150 100644 --- a/packages/evm/test/runCode.spec.ts +++ b/packages/evm/test/runCode.spec.ts @@ -1,11 +1,10 @@ +import { DefaultStateManager } from '@ethereumjs/statemanager' import { Account, Address } from '@ethereumjs/util' import { hexToBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' import { EVM } from '../src' -import { getEEI } from './utils' - const STOP = '00' const JUMP = '56' const JUMPDEST = '5b' @@ -23,8 +22,9 @@ const testCases = [ ] tape('VM.runCode: initial program counter', async (t) => { - const eei = await getEEI() - const evm = await EVM.create({ eei }) + const evm = await EVM.create({ + stateManager: new DefaultStateManager(), + }) for (const [i, testData] of testCases.entries()) { const runCodeArgs = { @@ -59,8 +59,9 @@ tape('VM.runCode: initial program counter', async (t) => { tape('VM.runCode: interpreter', (t) => { t.test('should return a EvmError as an exceptionError on the result', async (st) => { - const eei = await getEEI() - const evm = await EVM.create({ eei }) + const evm = await EVM.create({ + stateManager: new DefaultStateManager(), + }) const INVALID_opcode = 'fe' const runCodeArgs = { @@ -80,13 +81,19 @@ tape('VM.runCode: interpreter', (t) => { }) t.test('should throw on non-EvmError', async (st) => { - const eei = await getEEI() + const evm = await EVM.create({ + stateManager: new DefaultStateManager(), + }) + // NOTE: due to now throwing on `getContractStorage` if account does not exist + // this now means that if `runCode` is called and the address it runs on (default: zero address) + // does not exist, then if SSTORE/SLOAD is used, the runCode will immediately fail because StateManager now throws + // TODO: is this behavior which we should fix? (Either in StateManager OR in runCode where we load the account first, + // then re-put the account after (if account === undefined put empty account, such that the account exists)) const address = Address.fromString(`0x${'00'.repeat(20)}`) - await eei.putAccount(address, new Account()) - eei.putContractStorage = (..._args) => { + await evm.stateManager.putAccount(address, new Account()) + evm.stateManager.putContractStorage = (..._args) => { throw new Error('Test') } - const evm = await EVM.create({ eei }) const SSTORE = '55' const runCodeArgs = { @@ -106,8 +113,9 @@ tape('VM.runCode: interpreter', (t) => { tape('VM.runCode: RunCodeOptions', (t) => { t.test('should throw on negative value args', async (st) => { - const eei = await getEEI() - const evm = await EVM.create({ eei }) + const evm = await EVM.create({ + stateManager: new DefaultStateManager(), + }) const runCodeArgs = { value: BigInt(-10), diff --git a/packages/evm/test/stack.spec.ts b/packages/evm/test/stack.spec.ts index 4ebc724bf3..40598b4641 100644 --- a/packages/evm/test/stack.spec.ts +++ b/packages/evm/test/stack.spec.ts @@ -1,3 +1,4 @@ +import { DefaultStateManager } from '@ethereumjs/statemanager' import { Account, Address, bigIntToBytes, setLengthLeft } from '@ethereumjs/util' import { hexToBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' @@ -5,7 +6,7 @@ import * as tape from 'tape' import { EVM } from '../src' import { Stack } from '../src/stack' -import { createAccount, getEEI } from './utils' +import { createAccount } from './utils' tape('Stack', (t) => { t.test('should be empty initially', (st) => { @@ -129,8 +130,9 @@ tape('Stack', (t) => { t.test('stack items should not change if they are DUPed', async (st) => { const caller = new Address(hexToBytes('00000000000000000000000000000000000000ee')) const addr = new Address(hexToBytes('00000000000000000000000000000000000000ff')) - const eei = await getEEI() - const evm = await EVM.create({ eei }) + const evm = await EVM.create({ + stateManager: new DefaultStateManager(), + }) const account = createAccount(BigInt(0), BigInt(0)) const code = '60008080808060013382F15060005260206000F3' const expectedReturnValue = setLengthLeft(bigIntToBytes(BigInt(0)), 32) @@ -152,9 +154,9 @@ tape('Stack', (t) => { PUSH1 0x00 RETURN stack: [0, 0x20] (we thus return the stack item which was originally pushed as 0, and then DUPed) */ - await eei.putAccount(addr, account) - await eei.putContractCode(addr, hexToBytes(code)) - await eei.putAccount(caller, new Account(BigInt(0), BigInt(0x11))) + await evm.stateManager.putAccount(addr, account) + await evm.stateManager.putContractCode(addr, hexToBytes(code)) + await evm.stateManager.putAccount(caller, new Account(BigInt(0), BigInt(0x11))) const runCallArgs = { caller, gasLimit: BigInt(0xffffffffff), diff --git a/packages/evm/test/utils.ts b/packages/evm/test/utils.ts index c349187d39..3996153c76 100644 --- a/packages/evm/test/utils.ts +++ b/packages/evm/test/utils.ts @@ -1,19 +1,6 @@ -import { Chain, Common } from '@ethereumjs/common' -import { DefaultStateManager } from '@ethereumjs/statemanager' import { Account } from '@ethereumjs/util' import path from 'path' -import { Blockchain } from '../../blockchain/src' -import { EEI } from '../../vm/src/eei/eei' - -export async function getEEI() { - return new EEI( - new DefaultStateManager(), - new Common({ chain: Chain.Mainnet }), - await Blockchain.create() - ) -} - export function createAccount(nonce = BigInt(0), balance = BigInt(0xfff384)) { return new Account(nonce, balance) } diff --git a/packages/vm/src/eei/journaling.ts b/packages/statemanager/src/cache/journaling.ts similarity index 100% rename from packages/vm/src/eei/journaling.ts rename to packages/statemanager/src/cache/journaling.ts diff --git a/packages/statemanager/src/ethersStateManager.ts b/packages/statemanager/src/ethersStateManager.ts index 5194d942f1..8a05158e2e 100644 --- a/packages/statemanager/src/ethersStateManager.ts +++ b/packages/statemanager/src/ethersStateManager.ts @@ -6,8 +6,8 @@ import { ethers } from 'ethers' import { AccountCache, CacheType } from './cache' -import type { Proof, StateManager } from '.' -import type { AccountFields, StorageDump } from './interface' +import type { Proof } from '.' +import type { AccountFields, StateManagerInterface, StorageDump } from '@ethereumjs/common' import type { Address } from '@ethereumjs/util' const log = debug('statemanager') @@ -17,7 +17,7 @@ export interface EthersStateManagerOpts { blockTag: bigint | 'earliest' } -export class EthersStateManager implements StateManager { +export class EthersStateManager implements StateManagerInterface { private provider: ethers.providers.StaticJsonRpcProvider | ethers.providers.JsonRpcProvider private contractCache: Map private storageCache: Map> diff --git a/packages/statemanager/src/index.ts b/packages/statemanager/src/index.ts index 30083415e3..b7e980f7ad 100644 --- a/packages/statemanager/src/index.ts +++ b/packages/statemanager/src/index.ts @@ -1,4 +1,3 @@ export * from './cache' export * from './ethersStateManager' -export * from './interface' export * from './stateManager' diff --git a/packages/statemanager/src/interface.ts b/packages/statemanager/src/interface.ts deleted file mode 100644 index 747f630d22..0000000000 --- a/packages/statemanager/src/interface.ts +++ /dev/null @@ -1,39 +0,0 @@ -import type { Proof } from './stateManager' -import type { Account, Address } from '@ethereumjs/util' - -/** - * Storage values of an account - */ -export interface StorageDump { - [key: string]: string -} - -export type AccountFields = Partial> - -export interface StateAccess { - accountExists(address: Address): Promise - getAccount(address: Address): Promise - putAccount(address: Address, account: Account | undefined): Promise - deleteAccount(address: Address): Promise - modifyAccountFields(address: Address, accountFields: AccountFields): Promise - putContractCode(address: Address, value: Uint8Array): Promise - getContractCode(address: Address): Promise - getContractStorage(address: Address, key: Uint8Array): Promise - putContractStorage(address: Address, key: Uint8Array, value: Uint8Array): Promise - clearContractStorage(address: Address): Promise - checkpoint(): Promise - commit(): Promise - revert(): Promise - getStateRoot(): Promise - setStateRoot(stateRoot: Uint8Array, clearCache?: boolean): Promise - getProof?(address: Address, storageSlots: Uint8Array[]): Promise - verifyProof?(proof: Proof): Promise - hasStateRoot(root: Uint8Array): Promise -} - -export interface StateManager extends StateAccess { - copy(): StateManager - flush(): Promise - dumpStorage(address: Address): Promise - clearCaches(): void -} diff --git a/packages/statemanager/src/stateManager.ts b/packages/statemanager/src/stateManager.ts index 94f4a93aa3..9fbded98aa 100644 --- a/packages/statemanager/src/stateManager.ts +++ b/packages/statemanager/src/stateManager.ts @@ -1,3 +1,4 @@ +import { Chain, Common, Hardfork } from '@ethereumjs/common' import { RLP } from '@ethereumjs/rlp' import { Trie } from '@ethereumjs/trie' import { @@ -7,6 +8,7 @@ import { KECCAK256_NULL_S, KECCAK256_RLP, KECCAK256_RLP_S, + RIPEMD160_ADDRESS_STRING, bigIntToHex, bytesToHex, bytesToPrefixedHexString, @@ -15,6 +17,7 @@ import { hexStringToBytes, setLengthLeft, short, + toBytes, unpadBytes, utf8ToBytes, } from '@ethereumjs/util' @@ -23,10 +26,17 @@ import { keccak256 } from 'ethereum-cryptography/keccak' import { hexToBytes } from 'ethereum-cryptography/utils' import { AccountCache, CacheType, StorageCache } from './cache' - -import type { AccountFields, StateManager, StorageDump } from './interface' +import { Journaling } from './cache/journaling' + +import type { + AccessListItem, + AccountFields, + EVMStateManagerInterface, + StorageDump, +} from '@ethereumjs/common' import type { PrefixedHexString } from '@ethereumjs/util' import type { Debugger } from 'debug' +import type { AccessList } from 'ethers/lib/utils' export type StorageProof = { key: PrefixedHexString @@ -116,6 +126,11 @@ export interface DefaultStateManagerOpts { accountCacheOpts?: CacheOptions storageCacheOpts?: CacheOptions + + /** + * The common to use + */ + common?: Common } /** @@ -128,7 +143,7 @@ export interface DefaultStateManagerOpts { * The default state manager implementation uses a * `@ethereumjs/trie` trie as a data backend. */ -export class DefaultStateManager implements StateManager { +export class DefaultStateManager implements EVMStateManagerInterface { _debug: Debugger _accountCache?: AccountCache _storageCache?: StorageCache @@ -137,10 +152,36 @@ export class DefaultStateManager implements StateManager { _storageTries: { [key: string]: Trie } _codeCache: { [key: string]: Uint8Array } + // EIP-2929 address/storage trackers. + // This maps both the accessed accounts and the accessed storage slots. + // It is a Map(Address => StorageSlots) + // It is possible that the storage slots set is empty. This means that the address is warm. + // It is not possible to have an accessed storage slot on a cold address (which is why this structure works) + // Each call level tracks their access themselves. + // In case of a commit, copy everything if the value does not exist, to the level above + // In case of a revert, discard any warm slots. + // + // TODO: Switch to diff based version similar to _touchedStack + // (_accessStorage representing the actual state, separate _accessedStorageStack dictionary + // tracking the access diffs per commit) + protected _accessedStorage: Map>[] + + // Backup structure for address/storage tracker frames on reverts + // to also include on access list generation + protected _accessedStorageReverted: Map>[] + + protected _originalStorageCache: Map> + + protected readonly touchedJournal: Journaling + protected readonly _prefixCodeHashes: boolean protected readonly _accountCacheSettings: CacheSettings protected readonly _storageCacheSettings: CacheSettings + protected readonly _common: Common + + protected _checkpointCount: number + /** * StateManager is run in DEBUG mode (default: false) * Taken from DEBUG environment variable @@ -160,10 +201,20 @@ export class DefaultStateManager implements StateManager { this._debug = createDebugLogger('statemanager:statemanager') + this._common = opts.common ?? new Common({ chain: Chain.Mainnet }) + + this._checkpointCount = 0 + this._trie = opts.trie ?? new Trie({ useKeyHashing: true }) this._storageTries = {} this._codeCache = {} + this._originalStorageCache = new Map() + this._accessedStorage = [new Map()] + this._accessedStorageReverted = [new Map()] + + this.touchedJournal = new Journaling() + this._prefixCodeHashes = opts.prefixCodeHashes ?? true this._accountCacheSettings = { deactivate: opts.accountCacheOpts?.deactivate ?? false, @@ -215,12 +266,27 @@ export class DefaultStateManager implements StateManager { return account } + /** + * Checks if the `account` corresponding to `address` + * is empty or non-existent as defined in + * EIP-161 (https://eips.ethereum.org/EIPS/eip-161). + * @param address - Address to check + */ + async accountIsEmptyOrNonExistent(address: Address): Promise { + const account = await this.getAccount(address) + if (account === undefined || account.isEmpty()) { + return true + } + return false + } + /** * Saves an account into state under the provided `address`. * @param address - Address under which to store `account` * @param account - The account to store or undefined if to be deleted + * @param touch - If the account should be touched or not (for state clearing, see TangerineWhistle / SpuriousDragon hardforks) */ - async putAccount(address: Address, account: Account | undefined): Promise { + async putAccount(address: Address, account: Account | undefined, touch = false): Promise { if (this.DEBUG) { this._debug( `Save account address=${address} nonce=${account?.nonce} balance=${ @@ -244,6 +310,9 @@ export class DefaultStateManager implements StateManager { this._accountCache!.del(address) } } + if (touch) { + this.touchAccount(address) + } } /** @@ -268,8 +337,9 @@ export class DefaultStateManager implements StateManager { /** * Deletes an account from state under the provided `address`. * @param address - Address of the account which should be deleted + * @param touch - If the account should be touched or not (for state clearing, see TangerineWhistle / SpuriousDragon hardforks) */ - async deleteAccount(address: Address) { + async deleteAccount(address: Address, touch = false) { if (this.DEBUG) { this._debug(`Delete account ${address}`) } @@ -281,6 +351,41 @@ export class DefaultStateManager implements StateManager { if (!this._storageCacheSettings.deactivate) { this._storageCache?.clearContractStorage(address) } + if (touch) { + this.touchAccount(address) + } + } + + /** + * Marks an account as touched, according to the definition + * in [EIP-158](https://eips.ethereum.org/EIPS/eip-158). + * This happens when the account is triggered for a state-changing + * event. Touched accounts that are empty will be cleared + * at the end of the tx. + */ + protected touchAccount(address: Address): void { + this.touchedJournal.addJournalItem(address.toString().slice(2)) + } + + /** + * Removes accounts form the state trie that have been touched, + * as defined in EIP-161 (https://eips.ethereum.org/EIPS/eip-161). + */ + async cleanupTouchedAccounts(): Promise { + if (this._common.gteHardfork(Hardfork.SpuriousDragon) === true) { + const touchedArray = Array.from(this.touchedJournal.journal) + for (const addressHex of touchedArray) { + const address = new Address(hexToBytes(addressHex)) + const empty = await this.accountIsEmptyOrNonExistent(address) + if (empty) { + await this.deleteAccount(address) + if (this.DEBUG) { + this._debug(`Cleanup touched account address=${address} (>= SpuriousDragon)`) + } + } + } + } + this.touchedJournal.clear() } /** @@ -344,7 +449,7 @@ export class DefaultStateManager implements StateManager { * cache or does a lookup. * @private */ - async _getStorageTrie(address: Address, account: Account): Promise { + private async _getStorageTrie(address: Address, account: Account): Promise { // from storage cache const addressHex = bytesToHex(address.bytes) const storageTrie = this._storageTries[addressHex] @@ -392,13 +497,54 @@ export class DefaultStateManager implements StateManager { return decoded } + /** + * Caches the storage value associated with the provided `address` and `key` + * on first invocation, and returns the cached (original) value from then + * onwards. This is used to get the original value of a storage slot for + * computing gas costs according to EIP-1283. + * @param address - Address of the account to get the storage for + * @param key - Key in the account's storage to get the value for. Must be 32 bytes long. + */ + async getOriginalContractStorage(address: Address, key: Uint8Array): Promise { + if (key.length !== 32) { + throw new Error('Storage key must be 32 bytes long') + } + + const addressHex = address.toString() + const keyHex = bytesToHex(key) + + let map: Map + if (!this._originalStorageCache.has(addressHex)) { + map = new Map() + this._originalStorageCache.set(addressHex, map) + } else { + map = this._originalStorageCache.get(addressHex)! + } + + if (map.has(keyHex)) { + return map.get(keyHex)! + } else { + const current = await this.getContractStorage(address, key) + map.set(keyHex, current) + return current + } + } + + /** + * Clears the original storage cache. Refer to {@link StateManager.getOriginalContractStorage} + * for more explanation. Alias of the internal {@link StateManager._clearOriginalStorageCache} + */ + clearOriginalStorageCache(): void { + this._originalStorageCache = new Map() + } + /** * Modifies the storage trie of an account. * @private * @param address - Address of the account whose storage is to be modified * @param modifyTrie - Function to modify the storage trie of the account */ - async _modifyContractStorage( + private async _modifyContractStorage( address: Address, account: Account, modifyTrie: (storageTrie: Trie, done: Function) => void @@ -420,7 +566,7 @@ export class DefaultStateManager implements StateManager { }) } - async _writeContractStorage( + private async _writeContractStorage( address: Address, account: Account, key: Uint8Array, @@ -453,8 +599,14 @@ export class DefaultStateManager implements StateManager { * @param value - Value to set at `key` for account corresponding to `address`. * Cannot be more than 32 bytes. Leading zeros are stripped. * If it is a empty or filled with zeros, deletes the value. + * @param touch - If the account should be touched or not (for state clearing, see TangerineWhistle / SpuriousDragon hardforks) */ - async putContractStorage(address: Address, key: Uint8Array, value: Uint8Array): Promise { + async putContractStorage( + address: Address, + key: Uint8Array, + value: Uint8Array, + touch = false + ): Promise { if (key.length !== 32) { throw new Error('Storage key must be 32 bytes long') } @@ -475,13 +627,17 @@ export class DefaultStateManager implements StateManager { } else { await this._writeContractStorage(address, account, key, value) } + if (touch) { + this.touchAccount(address) + } } /** * Clears all storage entries for the account corresponding to `address`. * @param address - Address to clear the storage of + * @param touch - If the account should be touched or not (for state clearing, see TangerineWhistle / SpuriousDragon hardforks) */ - async clearContractStorage(address: Address): Promise { + async clearContractStorage(address: Address, touch = false): Promise { let account = await this.getAccount(address) if (!account) { account = new Account() @@ -491,6 +647,9 @@ export class DefaultStateManager implements StateManager { storageTrie.root(storageTrie.EMPTY_TRIE_ROOT) done() }) + if (touch) { + this.touchAccount(address) + } } /** @@ -502,6 +661,11 @@ export class DefaultStateManager implements StateManager { this._trie.checkpoint() this._storageCache?.checkpoint() this._accountCache?.checkpoint() + if (this._common.gteHardfork(Hardfork.Berlin)) { + this._accessedStorage.push(new Map()) + } + this._checkpointCount++ + this.touchedJournal.checkpoint() } /** @@ -513,6 +677,24 @@ export class DefaultStateManager implements StateManager { await this._trie.commit() this._storageCache?.commit() this._accountCache?.commit() + if (this._common.gteHardfork(Hardfork.Berlin)) { + // Copy the contents of the map of the current level to a map higher. + const storageMap = this._accessedStorage.pop() + if (storageMap) { + this._accessedStorageMerge(this._accessedStorage, storageMap) + } + } + this.touchedJournal.commit() + this._checkpointCount-- + + if (this._checkpointCount === 0) { + await this.flush() + this.clearOriginalStorageCache() + } + + if (this.DEBUG) { + this._debug(`state checkpoint committed`) + } } /** @@ -526,6 +708,21 @@ export class DefaultStateManager implements StateManager { this._accountCache?.revert() this._storageTries = {} this._codeCache = {} + if (this._common.gteHardfork(Hardfork.Berlin)) { + // setup cache checkpointing + const lastItem = this._accessedStorage.pop() + if (lastItem) { + this._accessedStorageReverted.push(lastItem) + } + } + this.touchedJournal.revert(RIPEMD160_ADDRESS_STRING) + + this._checkpointCount-- + + if (this._checkpointCount === 0) { + await this.flush() + this.clearOriginalStorageCache() + } } /** @@ -731,6 +928,137 @@ export class DefaultStateManager implements StateManager { this._codeCache = {} } + /** EIP-2929 logic + * This should only be called from within the EVM + */ + + /** + * Returns true if the address is warm in the current context + * @param address - The address (as a Uint8Array) to check + */ + isWarmedAddress(address: Uint8Array): boolean { + for (let i = this._accessedStorage.length - 1; i >= 0; i--) { + const currentMap = this._accessedStorage[i] + if (currentMap.has(bytesToHex(address))) { + return true + } + } + return false + } + + /** + * Add a warm address in the current context + * @param address - The address (as a Uint8Array) to check + */ + addWarmedAddress(address: Uint8Array): void { + const key = bytesToHex(address) + const storageSet = this._accessedStorage[this._accessedStorage.length - 1].get(key) + if (!storageSet) { + const emptyStorage = new Set() + this._accessedStorage[this._accessedStorage.length - 1].set(key, emptyStorage) + } + } + + /** + * Returns true if the slot of the address is warm + * @param address - The address (as a Uint8Array) to check + * @param slot - The slot (as a Uint8Array) to check + */ + isWarmedStorage(address: Uint8Array, slot: Uint8Array): boolean { + const addressKey = bytesToHex(address) + const storageKey = bytesToHex(slot) + + for (let i = this._accessedStorage.length - 1; i >= 0; i--) { + const currentMap = this._accessedStorage[i] + if (currentMap.has(addressKey) && currentMap.get(addressKey)!.has(storageKey)) { + return true + } + } + + return false + } + + /** + * Mark the storage slot in the address as warm in the current context + * @param address - The address (as a Uint8Array) to check + * @param slot - The slot (as a Uint8Array) to check + */ + addWarmedStorage(address: Uint8Array, slot: Uint8Array): void { + const addressKey = bytesToHex(address) + let storageSet = this._accessedStorage[this._accessedStorage.length - 1].get(addressKey) + if (!storageSet) { + storageSet = new Set() + this._accessedStorage[this._accessedStorage.length - 1].set(addressKey, storageSet!) + } + storageSet!.add(bytesToHex(slot)) + } + + /** + * Clear the warm accounts and storage. To be called after a transaction finished. + */ + clearWarmedAccounts(): void { + this._accessedStorage = [new Map()] + this._accessedStorageReverted = [new Map()] + } + + /** + * Generates an EIP-2930 access list + * + * Note: this method is not yet part of the {@link StateManager} interface. + * If not implemented, {@link VM.runTx} is not allowed to be used with the + * `reportAccessList` option and will instead throw. + * + * Note: there is an edge case on accessList generation where an + * internal call might revert without an accessList but pass if the + * accessList is used for a tx run (so the subsequent behavior might change). + * This edge case is not covered by this implementation. + * + * @param addressesRemoved - List of addresses to be removed from the final list + * @param addressesOnlyStorage - List of addresses only to be added in case of present storage slots + * + * @returns - an [@ethereumjs/tx](https://github.com/ethereumjs/ethereumjs-monorepo/packages/tx) `AccessList` + */ + generateAccessList( + addressesRemoved: Address[] = [], + addressesOnlyStorage: Address[] = [] + ): AccessList { + // Merge with the reverted storage list + const mergedStorage = [...this._accessedStorage, ...this._accessedStorageReverted] + + // Fold merged storage array into one Map + while (mergedStorage.length >= 2) { + const storageMap = mergedStorage.pop() + if (storageMap) { + this._accessedStorageMerge(mergedStorage, storageMap) + } + } + const folded = new Map([...mergedStorage[0].entries()].sort()) + + // Transfer folded map to final structure + const accessList: AccessList = [] + for (const [addressStr, slots] of folded.entries()) { + const address = Address.fromString(`0x${addressStr}`) + const check1 = addressesRemoved.find((a) => a.equals(address)) + const check2 = + addressesOnlyStorage.find((a) => a.equals(address)) !== undefined && slots.size === 0 + + if (!check1 && !check2) { + const storageSlots = Array.from(slots) + .map((s) => `0x${s}`) + .sort() + const accessListItem: AccessListItem = { + address: `0x${addressStr}`, + storageKeys: storageSlots, + } + accessList!.push(accessListItem) + } + } + + return accessList + } + + // End of EIP-2929 related logic + /** * Dumps the RLP-encoded storage values for an `account` specified by `address`. * @param address - The address of the `account` to return storage for @@ -764,6 +1092,47 @@ export class DefaultStateManager implements StateManager { }) } + /** + * Initializes the provided genesis state into the state trie. + * Will error if there are uncommitted checkpoints on the instance. + * @param initState address -> balance | [balance, code, storage] + */ + async generateCanonicalGenesis(initState: any): Promise { + if (this._checkpointCount !== 0) { + throw new Error('Cannot create genesis state with uncommitted checkpoints') + } + if (this.DEBUG) { + this._debug(`Save genesis state into the state trie`) + } + const addresses = Object.keys(initState) + for (const address of addresses) { + const addr = Address.fromString(address) + const state = initState[address] + if (!Array.isArray(state)) { + // Prior format: address -> balance + const account = Account.fromAccountData({ balance: state }) + await this.putAccount(addr, account) + } else { + // New format: address -> [balance, code, storage] + const [balance, code, storage, nonce] = state + const account = Account.fromAccountData({ balance, nonce }) + await this.putAccount(addr, account) + if (code !== undefined) { + await this.putContractCode(addr, toBytes(code)) + } + if (storage !== undefined) { + for (const [key, value] of storage) { + await this.putContractStorage(addr, toBytes(key), toBytes(value)) + } + } + } + } + await this.flush() + // If any empty accounts are put, these should not be marked as touched + // (when first tx is ran, this account is deleted when it cleans up the accounts) + this.touchedJournal.clear() + } + /** * Checks whether there is a state corresponding to a stateRoot */ @@ -785,6 +1154,30 @@ export class DefaultStateManager implements StateManager { } } + /** + * Merges a storage map into the last item of the accessed storage stack + */ + private _accessedStorageMerge( + storageList: Map | undefined>[], + storageMap: Map> + ) { + const mapTarget = storageList[storageList.length - 1] + + if (mapTarget !== undefined) { + // Note: storageMap is always defined here per definition (TypeScript cannot infer this) + for (const [addressString, slotSet] of storageMap) { + const addressExists = mapTarget.get(addressString) + if (!addressExists) { + mapTarget.set(addressString, new Set()) + } + const storageSet = mapTarget.get(addressString) + for (const value of slotSet) { + storageSet!.add(value) + } + } + } + } + /** * Copies the current instance of the `StateManager` * at the last fully committed point, i.e. as if all current @@ -798,7 +1191,7 @@ export class DefaultStateManager implements StateManager { * a large overhead here. * 2. Cache values are generally not copied along */ - copy(): StateManager { + copy(): DefaultStateManager { const trie = this._trie.copy(false) const prefixCodeHashes = this._prefixCodeHashes let accountCacheOpts = { ...this._accountCacheSettings } diff --git a/packages/statemanager/test/ethersStateManager.spec.ts b/packages/statemanager/test/ethersStateManager.spec.ts index 9953f6a15a..d19231349f 100644 --- a/packages/statemanager/test/ethersStateManager.spec.ts +++ b/packages/statemanager/test/ethersStateManager.spec.ts @@ -1,17 +1,13 @@ import { Block } from '@ethereumjs/block' -import { Chain, Common, Hardfork } from '@ethereumjs/common' -import { FeeMarketEIP1559Transaction, TransactionFactory } from '@ethereumjs/tx' import { Account, Address, bigIntToBytes, equalsBytes, - hexStringToBytes, setLengthLeft, utf8ToBytes, } from '@ethereumjs/util' -import { VM } from '@ethereumjs/vm' -import { BaseProvider, JsonRpcProvider, StaticJsonRpcProvider } from '@ethersproject/providers' +import { BaseProvider, StaticJsonRpcProvider } from '@ethersproject/providers' import * as tape from 'tape' import { EthersStateManager } from '../src/ethersStateManager' @@ -177,6 +173,7 @@ tape('Ethers State Manager API tests', async (t) => { } }) +/* TODO FIXME tape('runTx custom transaction test', async (t) => { if (isBrowser() === true) { // The `MockProvider` is not able to load JSON files dynamically in browser so skipped in browser tests @@ -188,7 +185,7 @@ tape('runTx custom transaction test', async (t) => { ? new StaticJsonRpcProvider(process.env.PROVIDER, 1) : new MockProvider() const state = new EthersStateManager({ provider, blockTag: 1n }) - const vm = await VM.create({ common, stateManager: state }) + const vm = await VM.create({ common, stateManager: state }) // TODO fix the type DefaultStateManager back to StateManagerInterface in VM const vitalikDotEth = Address.fromString('0xd8da6bf26964af9d7eed9e03e53415d37aa96045') const privateKey = hexStringToBytes( @@ -231,7 +228,7 @@ tape('runTx test: replay mainnet transactions', async (t) => { // Set the state manager to look at the state of the chain before the block has been executed blockTag: blockTag - 1n, }) - const vm = await VM.create({ common, stateManager: state }) + const vm = await VM.create({ common, stateManager: state }) const res = await vm.runTx({ tx }) t.equal(res.totalGasSpent, 21000n, 'calculated correct total gas spent for simple transfer') t.end() @@ -274,3 +271,4 @@ tape('runBlock test', async (t) => { } } }) +*/ diff --git a/packages/statemanager/test/oldeeitests.spec.ts b/packages/statemanager/test/oldeeitests.spec.ts new file mode 100644 index 0000000000..bd85a5044e --- /dev/null +++ b/packages/statemanager/test/oldeeitests.spec.ts @@ -0,0 +1,62 @@ +import { Account, Address } from '@ethereumjs/util' +import * as tape from 'tape' + +import { DefaultStateManager } from '../src' + +const ZeroAddress = Address.zero() + +tape('EEI.copy()', async (t) => { + const state = new DefaultStateManager() + const nonEmptyAccount = Account.fromAccountData({ nonce: 1 }) + await state.putAccount(ZeroAddress, nonEmptyAccount) + await state.checkpoint() + await state.commit() + const copy = state.copy() + t.equal( + (state as any)._common.hardfork(), + (copy as any)._common.hardfork(), + 'copied EEI should have the same hardfork' + ) + t.equal( + (await copy.getAccount(ZeroAddress))!.nonce, + (await state.getAccount(ZeroAddress))!.nonce, + 'copy should have same State data' + ) +}) + +tape('EEI', (t) => { + t.test('should return false on non-existing accounts', async (st) => { + const state = new DefaultStateManager() + st.notOk(await state.accountExists(ZeroAddress)) + st.ok(await state.accountIsEmptyOrNonExistent(ZeroAddress)) + st.end() + }) + + t.test( + 'should return false on non-existing accounts which once existed in state but are now gone', + async (st) => { + const state = new DefaultStateManager() + await state.putAccount(ZeroAddress, new Account()) + st.ok(await state.accountExists(ZeroAddress)) + st.ok(await state.accountIsEmptyOrNonExistent(ZeroAddress)) + // now put a non-empty account + const nonEmptyAccount = Account.fromAccountData({ nonce: 1 }) + await state.putAccount(ZeroAddress, nonEmptyAccount) + st.ok(await state.accountExists(ZeroAddress)) + st.notOk(await state.accountIsEmptyOrNonExistent(ZeroAddress)) + st.end() + } + ) + + t.test('should return true on existing accounts', async (st) => { + const state = new DefaultStateManager() + // create empty account + await state.putAccount(ZeroAddress, new Account()) + st.ok(await state.accountExists(ZeroAddress)) // sanity check: account exists before we delete it + st.ok(await state.accountIsEmptyOrNonExistent(ZeroAddress)) // it is obviously empty + await state.deleteAccount(ZeroAddress) // delete the account + st.notOk(await state.accountExists(ZeroAddress)) // account should not exist + st.ok(await state.accountIsEmptyOrNonExistent(ZeroAddress)) // account is empty + st.end() + }) +}) diff --git a/packages/vm/test/api/vmState.spec.ts b/packages/statemanager/test/vmState.spec.ts similarity index 84% rename from packages/vm/test/api/vmState.spec.ts rename to packages/statemanager/test/vmState.spec.ts index 2ff115ede9..0858ab8ff9 100644 --- a/packages/vm/test/api/vmState.spec.ts +++ b/packages/statemanager/test/vmState.spec.ts @@ -1,17 +1,25 @@ import { Blockchain } from '@ethereumjs/blockchain' import { Chain, Common, Hardfork } from '@ethereumjs/common' import { DefaultStateManager } from '@ethereumjs/statemanager' -import { Address } from '@ethereumjs/util' +import { Account, Address } from '@ethereumjs/util' import { hexToBytes, utf8ToBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' -import { VmState } from '../../src/eei/vmState' - -import { createAccount, isRunningInKarma } from './utils' +export function createAccount(nonce = BigInt(0), balance = BigInt(0xfff384)) { + return new Account(nonce, balance) +} +/** + * Checks if in a karma test runner. + * @returns boolean whether running in karma + */ +export function isRunningInKarma(): boolean { + // eslint-disable-next-line no-undef + return typeof (globalThis).window !== 'undefined' && (globalThis).window.__karma__ +} const StateManager = DefaultStateManager -tape('vmState', (t) => { +tape('stateManager', (t) => { // TODO (@Jochem): reactivate along EEI/VMState moving to VM /*t.test( 'should generate the genesis state root correctly for mainnet from ethereum/tests data', @@ -22,10 +30,10 @@ tape('vmState', (t) => { } const genesisData = getSingleFile('BasicTests/genesishashestest.json') - const vmState = new VmState({ stateManager: new StateManager() }) + const stateManager = new VmState({ stateManager: new StateManager() }) const blockchain = await Blockchain.create() - await vmState.generateCanonicalGenesis(blockchain.genesisState()) - const stateRoot = await vmState.getStateRoot() + await stateManager.generateCanonicalGenesis(blockchain.genesisState()) + const stateRoot = await stateManager.getStateRoot() st.equal( bytesToHex(stateRoot), genesisData.genesis_state_root, @@ -46,10 +54,9 @@ tape('vmState', (t) => { ) const stateManager = new StateManager({}) - const vmState = new VmState({ stateManager, common }) const blockchain = await Blockchain.create({ common }) - await vmState.generateCanonicalGenesis(blockchain.genesisState()) - const stateRoot = await vmState.getStateRoot() + await stateManager.generateCanonicalGenesis(blockchain.genesisState()) + const stateRoot = await stateManager.getStateRoot() st.deepEquals( stateRoot, @@ -82,11 +89,10 @@ tape('vmState', (t) => { for (const [chain, expectedStateRoot] of chains) { const common = new Common({ chain, hardfork: Hardfork.Chainstart }) const stateManager = new DefaultStateManager({}) - const vmState = new VmState({ stateManager, common }) const blockchain = await Blockchain.create({ common }) - await vmState.generateCanonicalGenesis(blockchain.genesisState()) - const stateRoot = await vmState.getStateRoot() + await stateManager.generateCanonicalGenesis(blockchain.genesisState()) + const stateRoot = await stateManager.getStateRoot() st.deepEquals( stateRoot, @@ -100,49 +106,48 @@ tape('vmState', (t) => { tape('Original storage cache', async (t) => { const stateManager = new DefaultStateManager() - const vmState = new VmState({ stateManager }) const address = new Address(hexToBytes('a94f5374fce5edbc8e2a8697c15331677e6ebf0b')) const account = createAccount() - await vmState.putAccount(address, account) + await stateManager.putAccount(address, account) const key = hexToBytes('1234567890123456789012345678901234567890123456789012345678901234') const value = hexToBytes('1234') t.test('should initially have empty storage value', async (st) => { - await vmState.checkpoint() - const res = await vmState.getContractStorage(address, key) + await stateManager.checkpoint() + const res = await stateManager.getContractStorage(address, key) st.deepEqual(res, new Uint8Array(0)) - const origRes = await (vmState).getOriginalContractStorage(address, key) + const origRes = await (stateManager).getOriginalContractStorage(address, key) st.deepEqual(origRes, new Uint8Array(0)) - await vmState.commit() + await stateManager.commit() st.end() }) t.test('should set original storage value', async (st) => { - await vmState.putContractStorage(address, key, value) - const res = await vmState.getContractStorage(address, key) + await stateManager.putContractStorage(address, key, value) + const res = await stateManager.getContractStorage(address, key) st.deepEqual(res, value) st.end() }) t.test('should get original storage value', async (st) => { - const res = await (vmState).getOriginalContractStorage(address, key) + const res = await (stateManager).getOriginalContractStorage(address, key) st.deepEqual(res, value) st.end() }) t.test('should return correct original value after modification', async (st) => { const newValue = hexToBytes('1235') - await vmState.putContractStorage(address, key, newValue) - const res = await vmState.getContractStorage(address, key) + await stateManager.putContractStorage(address, key, newValue) + const res = await stateManager.getContractStorage(address, key) st.deepEqual(res, newValue) - const origRes = await (vmState).getOriginalContractStorage(address, key) + const origRes = await (stateManager).getOriginalContractStorage(address, key) st.deepEqual(origRes, value) st.end() }) @@ -151,24 +156,24 @@ tape('Original storage cache', async (t) => { const key2 = hexToBytes('0000000000000000000000000000000000000000000000000000000000000012') const value2 = utf8ToBytes('12') const value3 = utf8ToBytes('123') - await vmState.putContractStorage(address, key2, value2) + await stateManager.putContractStorage(address, key2, value2) - let res = await vmState.getContractStorage(address, key2) + let res = await stateManager.getContractStorage(address, key2) st.deepEqual(res, value2) - let origRes = await (vmState).getOriginalContractStorage(address, key2) + let origRes = await (stateManager).getOriginalContractStorage(address, key2) st.deepEqual(origRes, value2) - await vmState.putContractStorage(address, key2, value3) + await stateManager.putContractStorage(address, key2, value3) - res = await vmState.getContractStorage(address, key2) + res = await stateManager.getContractStorage(address, key2) st.deepEqual(res, value3) - origRes = await (vmState).getOriginalContractStorage(address, key2) + origRes = await (stateManager).getOriginalContractStorage(address, key2) st.deepEqual(origRes, value2) // Check previous key - res = await vmState.getContractStorage(address, key) + res = await stateManager.getContractStorage(address, key) st.deepEqual(res, hexToBytes('1235')) - origRes = await (vmState).getOriginalContractStorage(address, key) + origRes = await (stateManager).getOriginalContractStorage(address, key) st.deepEqual(origRes, value) st.end() @@ -176,7 +181,7 @@ tape('Original storage cache', async (t) => { t.test("getOriginalContractStorage should validate the key's length", async (st) => { try { - await (vmState).getOriginalContractStorage(address, new Uint8Array(12)) + await (stateManager).getOriginalContractStorage(address, new Uint8Array(12)) } catch (e: any) { st.equal(e.message, 'Storage key must be 32 bytes long') st.end() @@ -203,11 +208,10 @@ tape('StateManager - generateAccessList', (tester) => { function getStateManagerAliases() { const stateManager = new DefaultStateManager() - const vmState = new VmState({ stateManager }) - const addA = vmState.addWarmedAddress.bind(vmState) - const addS = vmState.addWarmedStorage.bind(vmState) - const gen = vmState.generateAccessList.bind(vmState) - const sm = vmState + const addA = stateManager.addWarmedAddress.bind(stateManager) + const addS = stateManager.addWarmedStorage.bind(stateManager) + const gen = stateManager.generateAccessList.bind(stateManager) + const sm = stateManager return { addA, addS, gen, sm } } diff --git a/packages/tx/src/types.ts b/packages/tx/src/types.ts index a745593afe..1d0a02e3b5 100644 --- a/packages/tx/src/types.ts +++ b/packages/tx/src/types.ts @@ -23,8 +23,14 @@ import type { FeeMarketEIP1559Transaction } from './eip1559Transaction' import type { AccessListEIP2930Transaction } from './eip2930Transaction' import type { BlobEIP4844Transaction } from './eip4844Transaction' import type { Transaction } from './legacyTransaction' -import type { Common } from '@ethereumjs/common' -import type { AddressLike, BigIntLike, BytesLike, PrefixedHexString } from '@ethereumjs/util' +import type { AccessList, AccessListBytes, Common } from '@ethereumjs/common' +import type { AddressLike, BigIntLike, BytesLike } from '@ethereumjs/util' +export type { + AccessList, + AccessListBytes, + AccessListBytesItem, + AccessListItem, +} from '@ethereumjs/common' const Bytes20 = new ByteVectorType(20) const Bytes32 = new ByteVectorType(32) @@ -98,22 +104,6 @@ export interface TxOptions { allowUnlimitedInitCodeSize?: boolean } -/* - * Access List types - */ - -export type AccessListItem = { - address: PrefixedHexString - storageKeys: PrefixedHexString[] -} - -/* - * An Access List as a tuple of [address: Uint8Array, storageKeys: Uint8Array[]] - */ -export type AccessListBytesItem = [Uint8Array, Uint8Array[]] -export type AccessListBytes = AccessListBytesItem[] -export type AccessList = AccessListItem[] - export function isAccessListBytes(input: AccessListBytes | AccessList): input is AccessListBytes { if (input.length === 0) { return true diff --git a/packages/util/src/constants.ts b/packages/util/src/constants.ts index 5c2b174c1e..ee823d9d47 100644 --- a/packages/util/src/constants.ts +++ b/packages/util/src/constants.ts @@ -69,3 +69,5 @@ export const KECCAK256_RLP = hexToBytes(KECCAK256_RLP_S) export const RLP_EMPTY_STRING = Uint8Array.from([0x80]) export const MAX_WITHDRAWALS_PER_PAYLOAD = 16 + +export const RIPEMD160_ADDRESS_STRING = '0000000000000000000000000000000000000003' diff --git a/packages/vm/benchmarks/util.ts b/packages/vm/benchmarks/util.ts index e52f04a651..39510163a7 100644 --- a/packages/vm/benchmarks/util.ts +++ b/packages/vm/benchmarks/util.ts @@ -1,7 +1,7 @@ import { Account, Address, equalsBytes, toBytes } from '@ethereumjs/util' import { Common } from '@ethereumjs/common' import { Block } from '@ethereumjs/block' -import { StateManager, DefaultStateManager } from '@ethereumjs/statemanager' +import { DefaultStateManager } from '@ethereumjs/statemanager' import { RunBlockResult } from '../dist/types' import { Mockchain } from './mockchain' @@ -25,7 +25,7 @@ export async function getPreState( [k: string]: StateTestPreAccount }, common: Common -): Promise { +): Promise { const state = new DefaultStateManager() await state.checkpoint() for (const k in pre) { diff --git a/packages/vm/src/buildBlock.ts b/packages/vm/src/buildBlock.ts index f2a0ef6e56..c88ce1e5ea 100644 --- a/packages/vm/src/buildBlock.ts +++ b/packages/vm/src/buildBlock.ts @@ -133,7 +133,7 @@ export class BlockBuilder { this.headerData.coinbase !== undefined ? new Address(toBytes(this.headerData.coinbase)) : Address.zero() - await rewardAccount(this.vm.eei, coinbase, reward) + await rewardAccount(this.vm.stateManager, coinbase, reward) } /** @@ -149,7 +149,7 @@ export class BlockBuilder { if (amount === 0n) continue // Withdrawal amount is represented in Gwei so needs to be // converted to wei - await rewardAccount(this.vm.eei, address, amount * GWEI_TO_WEI) + await rewardAccount(this.vm.stateManager, address, amount * GWEI_TO_WEI) } } diff --git a/packages/vm/src/eei/eei.ts b/packages/vm/src/eei/eei.ts deleted file mode 100644 index f9e6240509..0000000000 --- a/packages/vm/src/eei/eei.ts +++ /dev/null @@ -1,104 +0,0 @@ -import { bytesToBigInt } from '@ethereumjs/util' - -import { VmState } from './vmState' - -import type { Common } from '@ethereumjs/common' -import type { EEIInterface } from '@ethereumjs/evm' -import type { StateManager } from '@ethereumjs/statemanager' -import type { Address } from '@ethereumjs/util' - -type Block = { - hash(): Uint8Array -} - -type Blockchain = { - getBlock(blockId: number): Promise - copy(): Blockchain -} - -/** - * External interface made available to EVM bytecode. Modeled after - * the ewasm EEI [spec](https://github.com/ewasm/design/blob/master/eth_interface.md). - * It includes methods for accessing/modifying state, calling or creating contracts, access - * to environment data among other things. - * The EEI instance also keeps artifacts produced by the bytecode such as logs - * and to-be-selfdestructed addresses. - */ -export class EEI extends VmState implements EEIInterface { - protected _common: Common - protected _blockchain: Blockchain - - constructor(stateManager: StateManager, common: Common, blockchain: Blockchain) { - super({ common, stateManager }) - this._common = common - this._blockchain = blockchain - } - - /** - * Returns balance of the given account. - * @param address - Address of account - */ - async getExternalBalance(address: Address): Promise { - const account = await this.getAccount(address) - if (!account) { - return BigInt(0) - } - return account.balance - } - - /** - * Get size of an account’s code. - * @param address - Address of account - */ - async getExternalCodeSize(address: Address): Promise { - const code = await this.getContractCode(address) - return BigInt(code.length) - } - - /** - * Returns code of an account. - * @param address - Address of account - */ - async getExternalCode(address: Address): Promise { - return this.getContractCode(address) - } - - /** - * Returns Gets the hash of one of the 256 most recent complete blocks. - * @param num - Number of block - */ - async getBlockHash(num: bigint): Promise { - const block = await this._blockchain.getBlock(Number(num)) - return bytesToBigInt(block!.hash()) - } - - /** - * Storage 256-bit value into storage of an address - * @param address Address to store into - * @param key Storage key - * @param value Storage value - */ - async storageStore(address: Address, key: Uint8Array, value: Uint8Array): Promise { - await this.putContractStorage(address, key, value) - } - - /** - * Loads a 256-bit value to memory from persistent storage. - * @param address Address to get storage key value from - * @param key Storage key - * @param original If true, return the original storage value (default: false) - */ - async storageLoad(address: Address, key: Uint8Array, original = false): Promise { - if (original) { - return this.getOriginalContractStorage(address, key) - } else { - return this.getContractStorage(address, key) - } - } - - public copy() { - const common = this._common.copy() - common.setHardfork(this._common.hardfork()) - return new EEI(this._stateManager.copy(), common, this._blockchain.copy()) - } -} diff --git a/packages/vm/src/eei/vmState.ts b/packages/vm/src/eei/vmState.ts deleted file mode 100644 index 9bc9b9876b..0000000000 --- a/packages/vm/src/eei/vmState.ts +++ /dev/null @@ -1,489 +0,0 @@ -import { Chain, Common, Hardfork } from '@ethereumjs/common' -import { ripemdPrecompileAddress } from '@ethereumjs/evm/dist/precompiles' -import { Account, Address, toBytes } from '@ethereumjs/util' -import { debug as createDebugLogger } from 'debug' -import { bytesToHex, hexToBytes } from 'ethereum-cryptography/utils' - -import { Journaling } from './journaling' - -import type { EVMStateAccess } from '@ethereumjs/evm/dist/types' -import type { AccountFields, StateManager } from '@ethereumjs/statemanager' -import type { AccessList, AccessListItem } from '@ethereumjs/tx' -import type { Debugger } from 'debug' - -type AddressHex = string - -export class VmState implements EVMStateAccess { - protected _common: Common - protected _debug: Debugger - - protected _checkpointCount: number - protected _stateManager: StateManager - - // EIP-2929 address/storage trackers. - // This maps both the accessed accounts and the accessed storage slots. - // It is a Map(Address => StorageSlots) - // It is possible that the storage slots set is empty. This means that the address is warm. - // It is not possible to have an accessed storage slot on a cold address (which is why this structure works) - // Each call level tracks their access themselves. - // In case of a commit, copy everything if the value does not exist, to the level above - // In case of a revert, discard any warm slots. - // - // TODO: Switch to diff based version similar to _touchedStack - // (_accessStorage representing the actual state, separate _accessedStorageStack dictionary - // tracking the access diffs per commit) - protected _accessedStorage: Map>[] - - // Backup structure for address/storage tracker frames on reverts - // to also include on access list generation - protected _accessedStorageReverted: Map>[] - - protected _originalStorageCache: Map> - - protected readonly touchedJournal: Journaling - - protected readonly DEBUG: boolean = false - - constructor({ common, stateManager }: { common?: Common; stateManager: StateManager }) { - this._checkpointCount = 0 - this._stateManager = stateManager - this._common = common ?? new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Petersburg }) - this._originalStorageCache = new Map() - this._accessedStorage = [new Map()] - this._accessedStorageReverted = [new Map()] - - this.touchedJournal = new Journaling() - - // Skip DEBUG calls unless 'ethjs' included in environmental DEBUG variables - this.DEBUG = process?.env?.DEBUG?.includes('ethjs') ?? false - - this._debug = createDebugLogger('vm:state') - } - - /** - * Checkpoints the current state of the StateManager instance. - * State changes that follow can then be committed by calling - * `commit` or `reverted` by calling rollback. - * - * Partial implementation, called from the subclass. - */ - async checkpoint(): Promise { - if (this._common.gteHardfork(Hardfork.Berlin)) { - this._accessedStorage.push(new Map()) - } - await this._stateManager.checkpoint() - this._checkpointCount++ - this.touchedJournal.checkpoint() - - if (this.DEBUG) { - this._debug('-'.repeat(100)) - this._debug(`state checkpoint`) - } - } - - async commit(): Promise { - if (this._common.gteHardfork(Hardfork.Berlin)) { - // Copy the contents of the map of the current level to a map higher. - const storageMap = this._accessedStorage.pop() - if (storageMap) { - this._accessedStorageMerge(this._accessedStorage, storageMap) - } - } - await this._stateManager.commit() - this.touchedJournal.commit() - this._checkpointCount-- - - if (this._checkpointCount === 0) { - await this._stateManager.flush() - this._clearOriginalStorageCache() - } - - if (this.DEBUG) { - this._debug(`state checkpoint committed`) - } - } - - /** - * Reverts the current change-set to the instance since the - * last call to checkpoint. - * - * Partial implementation , called from the subclass. - */ - async revert(): Promise { - if (this._common.gteHardfork(Hardfork.Berlin)) { - // setup cache checkpointing - const lastItem = this._accessedStorage.pop() - if (lastItem) { - this._accessedStorageReverted.push(lastItem) - } - } - await this._stateManager.revert() - this.touchedJournal.revert(ripemdPrecompileAddress) - - this._checkpointCount-- - - if (this._checkpointCount === 0) { - await this._stateManager.flush() - this._clearOriginalStorageCache() - } - - if (this.DEBUG) { - this._debug(`state checkpoint reverted`) - } - } - - async getAccount(address: Address): Promise { - return this._stateManager.getAccount(address) - } - - async putAccount(address: Address, account: Account): Promise { - await this._stateManager.putAccount(address, account) - this.touchAccount(address) - } - - async modifyAccountFields(address: Address, accountFields: AccountFields): Promise { - return this._stateManager.modifyAccountFields(address, accountFields) - } - - /** - * Deletes an account from state under the provided `address`. The account will also be removed from the state trie. - * @param address - Address of the account which should be deleted - */ - async deleteAccount(address: Address) { - await this._stateManager.deleteAccount(address) - this.touchAccount(address) - } - - async getContractCode(address: Address): Promise { - return this._stateManager.getContractCode(address) - } - - async putContractCode(address: Address, value: Uint8Array): Promise { - return this._stateManager.putContractCode(address, value) - } - - async getContractStorage(address: Address, key: Uint8Array): Promise { - return this._stateManager.getContractStorage(address, key) - } - - async putContractStorage(address: Address, key: Uint8Array, value: Uint8Array) { - await this._stateManager.putContractStorage(address, key, value) - this.touchAccount(address) - } - - async clearContractStorage(address: Address) { - await this._stateManager.clearContractStorage(address) - this.touchAccount(address) - } - - async accountExists(address: Address): Promise { - return this._stateManager.accountExists(address) - } - - async setStateRoot(stateRoot: Uint8Array, clearCache: boolean = true): Promise { - if (this._checkpointCount !== 0) { - throw new Error('Cannot set state root with uncommitted checkpoints') - } - return this._stateManager.setStateRoot(stateRoot, clearCache) - } - - async getStateRoot(): Promise { - return this._stateManager.getStateRoot() - } - - async hasStateRoot(root: Uint8Array): Promise { - return this._stateManager.hasStateRoot(root) - } - - /** - * Marks an account as touched, according to the definition - * in [EIP-158](https://eips.ethereum.org/EIPS/eip-158). - * This happens when the account is triggered for a state-changing - * event. Touched accounts that are empty will be cleared - * at the end of the tx. - */ - touchAccount(address: Address): void { - this.touchedJournal.addJournalItem(address.toString().slice(2)) - } - - /** - * Merges a storage map into the last item of the accessed storage stack - */ - private _accessedStorageMerge( - storageList: Map | undefined>[], - storageMap: Map> - ) { - const mapTarget = storageList[storageList.length - 1] - - if (mapTarget !== undefined) { - // Note: storageMap is always defined here per definition (TypeScript cannot infer this) - for (const [addressString, slotSet] of storageMap) { - const addressExists = mapTarget.get(addressString) - if (!addressExists) { - mapTarget.set(addressString, new Set()) - } - const storageSet = mapTarget.get(addressString) - for (const value of slotSet) { - storageSet!.add(value) - } - } - } - } - - /** - * Initializes the provided genesis state into the state trie. - * Will error if there are uncommitted checkpoints on the instance. - * @param initState address -> balance | [balance, code, storage] - */ - async generateCanonicalGenesis(initState: any): Promise { - if (this._checkpointCount !== 0) { - throw new Error('Cannot create genesis state with uncommitted checkpoints') - } - if (this.DEBUG) { - this._debug(`Save genesis state into the state trie`) - } - const addresses = Object.keys(initState) - for (const address of addresses) { - const addr = Address.fromString(address) - const state = initState[address] - if (!Array.isArray(state)) { - // Prior format: address -> balance - const account = Account.fromAccountData({ balance: state }) - await this.putAccount(addr, account) - } else { - // New format: address -> [balance, code, storage] - const [balance, code, storage, nonce] = state - const account = Account.fromAccountData({ balance, nonce }) - await this.putAccount(addr, account) - if (code !== undefined) { - await this.putContractCode(addr, toBytes(code)) - } - if (storage !== undefined) { - for (const [key, value] of storage) { - await this.putContractStorage(addr, toBytes(key), toBytes(value)) - } - } - } - } - await this._stateManager.flush() - // If any empty accounts are put, these should not be marked as touched - // (when first tx is ran, this account is deleted when it cleans up the accounts) - this.touchedJournal.clear() - } - - /** - * Removes accounts form the state trie that have been touched, - * as defined in EIP-161 (https://eips.ethereum.org/EIPS/eip-161). - */ - async cleanupTouchedAccounts(): Promise { - if (this._common.gteHardfork(Hardfork.SpuriousDragon) === true) { - const touchedArray = Array.from(this.touchedJournal.journal) - for (const addressHex of touchedArray) { - const address = new Address(hexToBytes(addressHex)) - const empty = await this.accountIsEmptyOrNonExistent(address) - if (empty) { - await this._stateManager.deleteAccount(address) - if (this.DEBUG) { - this._debug(`Cleanup touched account address=${address} (>= SpuriousDragon)`) - } - } - } - } - this.touchedJournal.clear() - } - - /** - * Caches the storage value associated with the provided `address` and `key` - * on first invocation, and returns the cached (original) value from then - * onwards. This is used to get the original value of a storage slot for - * computing gas costs according to EIP-1283. - * @param address - Address of the account to get the storage for - * @param key - Key in the account's storage to get the value for. Must be 32 bytes long. - */ - protected async getOriginalContractStorage( - address: Address, - key: Uint8Array - ): Promise { - if (key.length !== 32) { - throw new Error('Storage key must be 32 bytes long') - } - - const addressHex = address.toString() - const keyHex = bytesToHex(key) - - let map: Map - if (!this._originalStorageCache.has(addressHex)) { - map = new Map() - this._originalStorageCache.set(addressHex, map) - } else { - map = this._originalStorageCache.get(addressHex)! - } - - if (map.has(keyHex)) { - return map.get(keyHex)! - } else { - const current = await this.getContractStorage(address, key) - map.set(keyHex, current) - return current - } - } - - /** - * Clears the original storage cache. Refer to {@link StateManager.getOriginalContractStorage} - * for more explanation. - */ - _clearOriginalStorageCache(): void { - this._originalStorageCache = new Map() - } - - /** - * Clears the original storage cache. Refer to {@link StateManager.getOriginalContractStorage} - * for more explanation. Alias of the internal {@link StateManager._clearOriginalStorageCache} - */ - clearOriginalStorageCache(): void { - this._clearOriginalStorageCache() - } - - /** EIP-2929 logic - * This should only be called from within the EVM - */ - - /** - * Returns true if the address is warm in the current context - * @param address - The address (as a Uint8Array) to check - */ - isWarmedAddress(address: Uint8Array): boolean { - for (let i = this._accessedStorage.length - 1; i >= 0; i--) { - const currentMap = this._accessedStorage[i] - if (currentMap.has(bytesToHex(address))) { - return true - } - } - return false - } - - /** - * Add a warm address in the current context - * @param address - The address (as a Uint8Array) to check - */ - addWarmedAddress(address: Uint8Array): void { - const key = bytesToHex(address) - const storageSet = this._accessedStorage[this._accessedStorage.length - 1].get(key) - if (!storageSet) { - const emptyStorage = new Set() - this._accessedStorage[this._accessedStorage.length - 1].set(key, emptyStorage) - } - } - - /** - * Returns true if the slot of the address is warm - * @param address - The address (as a Uint8Array) to check - * @param slot - The slot (as a Uint8Array) to check - */ - isWarmedStorage(address: Uint8Array, slot: Uint8Array): boolean { - const addressKey = bytesToHex(address) - const storageKey = bytesToHex(slot) - - for (let i = this._accessedStorage.length - 1; i >= 0; i--) { - const currentMap = this._accessedStorage[i] - if (currentMap.has(addressKey) && currentMap.get(addressKey)!.has(storageKey)) { - return true - } - } - - return false - } - - /** - * Mark the storage slot in the address as warm in the current context - * @param address - The address (as a Uint8Array) to check - * @param slot - The slot (as a Uint8Array) to check - */ - addWarmedStorage(address: Uint8Array, slot: Uint8Array): void { - const addressKey = bytesToHex(address) - let storageSet = this._accessedStorage[this._accessedStorage.length - 1].get(addressKey) - if (!storageSet) { - storageSet = new Set() - this._accessedStorage[this._accessedStorage.length - 1].set(addressKey, storageSet!) - } - storageSet!.add(bytesToHex(slot)) - } - - /** - * Clear the warm accounts and storage. To be called after a transaction finished. - */ - clearWarmedAccounts(): void { - this._accessedStorage = [new Map()] - this._accessedStorageReverted = [new Map()] - } - - /** - * Generates an EIP-2930 access list - * - * Note: this method is not yet part of the {@link StateManager} interface. - * If not implemented, {@link VM.runTx} is not allowed to be used with the - * `reportAccessList` option and will instead throw. - * - * Note: there is an edge case on accessList generation where an - * internal call might revert without an accessList but pass if the - * accessList is used for a tx run (so the subsequent behavior might change). - * This edge case is not covered by this implementation. - * - * @param addressesRemoved - List of addresses to be removed from the final list - * @param addressesOnlyStorage - List of addresses only to be added in case of present storage slots - * - * @returns - an [@ethereumjs/tx](https://github.com/ethereumjs/ethereumjs-monorepo/packages/tx) `AccessList` - */ - generateAccessList( - addressesRemoved: Address[] = [], - addressesOnlyStorage: Address[] = [] - ): AccessList { - // Merge with the reverted storage list - const mergedStorage = [...this._accessedStorage, ...this._accessedStorageReverted] - - // Fold merged storage array into one Map - while (mergedStorage.length >= 2) { - const storageMap = mergedStorage.pop() - if (storageMap) { - this._accessedStorageMerge(mergedStorage, storageMap) - } - } - const folded = new Map([...mergedStorage[0].entries()].sort()) - - // Transfer folded map to final structure - const accessList: AccessList = [] - for (const [addressStr, slots] of folded.entries()) { - const address = Address.fromString(`0x${addressStr}`) - const check1 = addressesRemoved.find((a) => a.equals(address)) - const check2 = - addressesOnlyStorage.find((a) => a.equals(address)) !== undefined && slots.size === 0 - - if (!check1 && !check2) { - const storageSlots = Array.from(slots) - .map((s) => `0x${s}`) - .sort() - const accessListItem: AccessListItem = { - address: `0x${addressStr}`, - storageKeys: storageSlots, - } - accessList!.push(accessListItem) - } - } - - return accessList - } - - /** - * Checks if the `account` corresponding to `address` - * is empty or non-existent as defined in - * EIP-161 (https://eips.ethereum.org/EIPS/eip-161). - * @param address - Address to check - */ - async accountIsEmptyOrNonExistent(address: Address): Promise { - const account = await this._stateManager.getAccount(address) - if (account === undefined || account.isEmpty()) { - return true - } - return false - } -} diff --git a/packages/vm/src/index.ts b/packages/vm/src/index.ts index 8f0d0bf324..8aafba025c 100644 --- a/packages/vm/src/index.ts +++ b/packages/vm/src/index.ts @@ -1,4 +1,3 @@ export { Bloom } from './bloom/index' -export * from './eei/eei' export * from './types' export { VM } from './vm' diff --git a/packages/vm/src/runBlock.ts b/packages/vm/src/runBlock.ts index 3c52926ce9..c1d1da47f2 100644 --- a/packages/vm/src/runBlock.ts +++ b/packages/vm/src/runBlock.ts @@ -28,7 +28,7 @@ import type { TxReceipt, } from './types' import type { VM } from './vm' -import type { EVMStateAccess } from '@ethereumjs/evm' +import type { EVMStateManagerInterface } from '@ethereumjs/common' const debug = createDebugLogger('vm:block') @@ -40,7 +40,7 @@ const DAORefundContract = DAOConfig.DAORefundContract * @ignore */ export async function runBlock(this: VM, opts: RunBlockOpts): Promise { - const state = this.eei + const state = this.stateManager const { root } = opts const clearCache = opts.clearCache ?? true let { block } = opts @@ -254,7 +254,7 @@ async function applyBlock(this: VM, block: Block, opts: RunBlockOpts) { const blockResults = await applyTransactions.bind(this)(block, opts) if (this._common.isActivatedEIP(4895)) { await assignWithdrawals.bind(this)(block) - await this.eei.cleanupTouchedAccounts() + await this.stateManager.cleanupTouchedAccounts() } // Pay ommers and miners if (block._common.consensusType() === ConsensusType.ProofOfWork) { @@ -338,7 +338,7 @@ async function applyTransactions(this: VM, block: Block, opts: RunBlockOpts) { } async function assignWithdrawals(this: VM, block: Block): Promise { - const state = this.eei + const state = this.stateManager const withdrawals = block.withdrawals! for (const withdrawal of withdrawals) { const { address, amount } = withdrawal @@ -358,7 +358,7 @@ async function assignBlockRewards(this: VM, block: Block): Promise { if (this.DEBUG) { debug(`Assign block rewards`) } - const state = this.eei + const state = this.stateManager const minerReward = this._common.param('pow', 'minerReward') const ommers = block.uncleHeaders // Reward ommers @@ -399,7 +399,7 @@ export function calculateMinerReward(minerReward: bigint, ommersNum: number): bi } export async function rewardAccount( - state: EVMStateAccess, + state: EVMStateManagerInterface, address: Address, reward: bigint ): Promise { @@ -408,7 +408,7 @@ export async function rewardAccount( account = new Account() } account.balance += reward - await state.putAccount(address, account) + await state.putAccount(address, account, true) return account } @@ -436,10 +436,10 @@ export function encodeReceipt(receipt: TxReceipt, txType: number) { /** * Apply the DAO fork changes to the VM */ -async function _applyDAOHardfork(state: EVMStateAccess) { +async function _applyDAOHardfork(state: EVMStateManagerInterface) { const DAORefundContractAddress = new Address(hexToBytes(DAORefundContract)) if ((await state.accountExists(DAORefundContractAddress)) === false) { - await state.putAccount(DAORefundContractAddress, new Account()) + await state.putAccount(DAORefundContractAddress, new Account(), true) } let DAORefundAccount = await state.getAccount(DAORefundContractAddress) if (DAORefundAccount === undefined) { @@ -456,11 +456,11 @@ async function _applyDAOHardfork(state: EVMStateAccess) { DAORefundAccount.balance += account.balance // clear the accounts' balance account.balance = BigInt(0) - await state.putAccount(address, account) + await state.putAccount(address, account, true) } // finally, put the Refund Account - await state.putAccount(DAORefundContractAddress, DAORefundAccount) + await state.putAccount(DAORefundContractAddress, DAORefundAccount, true) } async function _genTxTrie(block: Block) { diff --git a/packages/vm/src/runTx.ts b/packages/vm/src/runTx.ts index a41f3a1e41..66a9a239ae 100644 --- a/packages/vm/src/runTx.ts +++ b/packages/vm/src/runTx.ts @@ -88,7 +88,7 @@ export async function runTx(this: VM, opts: RunTxOpts): Promise { throw new Error(msg) } - const state = this.eei + const state = this.stateManager if (opts.reportAccessList === true && !('generateAccessList' in state)) { const msg = _errorMsg( @@ -127,16 +127,6 @@ export async function runTx(this: VM, opts: RunTxOpts): Promise { ) throw new Error(msg) } - if (opts.reportAccessList === true && !('generateAccessList' in state)) { - await state.revert() - const msg = _errorMsg( - 'StateManager needs to implement generateAccessList() when running with reportAccessList option', - this, - opts.block, - opts.tx - ) - throw new Error(msg) - } if ( opts.tx.supports(Capability.EIP1559FeeMarket) && this._common.isActivatedEIP(1559) === false @@ -197,7 +187,7 @@ export async function runTx(this: VM, opts: RunTxOpts): Promise { } async function _runTx(this: VM, opts: RunTxOpts): Promise { - const state = this.eei + const state = this.stateManager const { tx, block } = opts @@ -293,7 +283,7 @@ async function _runTx(this: VM, opts: RunTxOpts): Promise { if (tx.supports(Capability.EIP1559FeeMarket) === false) { // if skipBalance and not EIP1559 transaction, ensure caller balance is enough to run transaction fromAccount.balance = upFrontCost - await this.stateManager.putAccount(caller, fromAccount) + await this.stateManager.putAccount(caller, fromAccount, true) } } else { const msg = _errorMsg( @@ -356,7 +346,7 @@ async function _runTx(this: VM, opts: RunTxOpts): Promise { if (opts.skipBalance === true && fromAccount.balance < maxCost) { // if skipBalance, ensure caller balance is enough to run transaction fromAccount.balance = maxCost - await this.stateManager.putAccount(caller, fromAccount) + await this.stateManager.putAccount(caller, fromAccount, true) } else { const msg = _errorMsg( `sender doesn't have enough funds to send tx. The max cost is: ${maxCost} and the sender's account (${caller}) only has: ${balance}`, @@ -415,7 +405,7 @@ async function _runTx(this: VM, opts: RunTxOpts): Promise { if (opts.skipBalance === true && fromAccount.balance < BigInt(0)) { fromAccount.balance = BigInt(0) } - await state.putAccount(caller, fromAccount) + await state.putAccount(caller, fromAccount, true) if (this.DEBUG) { debug(`Update fromAccount (caller) balance (-> ${fromAccount.balance}))`) } @@ -506,7 +496,7 @@ async function _runTx(this: VM, opts: RunTxOpts): Promise { const actualTxCost = results.totalGasSpent * gasPrice const txCostDiff = txCost - actualTxCost fromAccount.balance += txCostDiff - await state.putAccount(caller, fromAccount) + await state.putAccount(caller, fromAccount, true) if (this.DEBUG) { debug( `Refunded txCostDiff (${txCostDiff}) to fromAccount (caller) balance (-> ${fromAccount.balance})` @@ -535,7 +525,7 @@ async function _runTx(this: VM, opts: RunTxOpts): Promise { // Put the miner account into the state. If the balance of the miner account remains zero, note that // the state.putAccount function puts this into the "touched" accounts. This will thus be removed when // we clean the touched accounts below in case we are in a fork >= SpuriousDragon - await state.putAccount(miner, minerAccount) + await state.putAccount(miner, minerAccount, true) if (this.DEBUG) { debug(`tx update miner account (${miner}) balance (-> ${minerAccount.balance})`) } @@ -547,14 +537,16 @@ async function _runTx(this: VM, opts: RunTxOpts): Promise { const keys = Object.keys(results.execResult.selfdestruct) for (const k of keys) { const address = new Address(hexToBytes(k)) - await state.deleteAccount(address) + await state.deleteAccount(address, true) if (this.DEBUG) { debug(`tx selfdestruct on address=${address}`) } } } - await state.cleanupTouchedAccounts() + if (this._common.gteHardfork(Hardfork.SpuriousDragon)) { + await state.cleanupTouchedAccounts() + } state.clearOriginalStorageCache() // Generate the tx receipt diff --git a/packages/vm/src/types.ts b/packages/vm/src/types.ts index 40469b4791..fd8ab16024 100644 --- a/packages/vm/src/types.ts +++ b/packages/vm/src/types.ts @@ -1,9 +1,8 @@ import type { Bloom } from './bloom' import type { Block, BlockOptions, HeaderData } from '@ethereumjs/block' import type { BlockchainInterface } from '@ethereumjs/blockchain' -import type { Common } from '@ethereumjs/common' -import type { EEIInterface, EVMInterface, EVMResult, Log } from '@ethereumjs/evm' -import type { StateManager } from '@ethereumjs/statemanager' +import type { Common, EVMStateManagerInterface } from '@ethereumjs/common' +import type { EVM, EVMResult, Log } from '@ethereumjs/evm' import type { AccessList, TypedTransaction } from '@ethereumjs/tx' import type { BigIntLike, WithdrawalData } from '@ethereumjs/util' export type TxReceipt = PreByzantiumTxReceipt | PostByzantiumTxReceipt | EIP4844BlobTxReceipt @@ -101,7 +100,7 @@ export interface VMOpts { /** * A {@link StateManager} instance to use as the state store */ - stateManager?: StateManager + stateManager?: EVMStateManagerInterface /** * A {@link Blockchain} object for storing/retrieving blocks */ @@ -147,15 +146,10 @@ export interface VMOpts { */ hardforkByTTD?: BigIntLike - /** - * Use a custom EEI for the EVM. If this is not present, use the default EEI. - */ - eei?: EEIInterface - /** * Use a custom EVM to run Messages on. If this is not present, use the default EVM. */ - evm?: EVMInterface + evm?: EVM } /** diff --git a/packages/vm/src/vm.ts b/packages/vm/src/vm.ts index c3e89a4e43..ee3e3a1375 100644 --- a/packages/vm/src/vm.ts +++ b/packages/vm/src/vm.ts @@ -7,7 +7,6 @@ import { hexToBytes } from 'ethereum-cryptography/utils' import { promisify } from 'util' import { buildBlock } from './buildBlock' -import { EEI } from './eei/eei' import { runBlock } from './runBlock' import { runTx } from './runTx' @@ -22,8 +21,7 @@ import type { VMOpts, } from './types' import type { BlockchainInterface } from '@ethereumjs/blockchain' -import type { EEIInterface, EVMInterface } from '@ethereumjs/evm' -import type { StateManager } from '@ethereumjs/statemanager' +import type { EVMStateManagerInterface } from '@ethereumjs/common' /** * Execution engine which can be used to run a blockchain, individual @@ -35,7 +33,7 @@ export class VM { /** * The StateManager used by the VM */ - readonly stateManager: StateManager + readonly stateManager: EVMStateManagerInterface /** * The blockchain the VM operates on @@ -48,8 +46,7 @@ export class VM { /** * The EVM used for bytecode execution */ - readonly evm: EVMInterface - readonly eei: EEIInterface + readonly evm: EVM protected readonly _opts: VMOpts protected _isInitialized: boolean = false @@ -108,32 +105,19 @@ export class VM { if (opts.stateManager) { this.stateManager = opts.stateManager } else { - this.stateManager = new DefaultStateManager({}) + this.stateManager = new DefaultStateManager({ common: this._common }) } this.blockchain = opts.blockchain ?? new (Blockchain as any)({ common: this._common }) // TODO tests - if (opts.eei !== undefined) { - if (opts.evm !== undefined) { - throw new Error('cannot specify EEI if EVM opt provided') - } - this.eei = opts.eei - } else { - if (opts.evm !== undefined) { - this.eei = opts.evm.eei - } else { - this.eei = new EEI(this.stateManager, this._common, this.blockchain) - } - } - - // TODO tests - if (opts.evm !== undefined) { + if (opts.evm) { this.evm = opts.evm } else { this.evm = new EVM({ common: this._common, - eei: this.eei, + stateManager: this.stateManager, + blockchain: this.blockchain, }) } @@ -165,7 +149,7 @@ export class VM { if (!this._opts.stateManager) { if (this._opts.activateGenesisState === true) { if (typeof (this.blockchain).genesisState === 'function') { - await this.eei.generateCanonicalGenesis((this.blockchain).genesisState()) + await this.stateManager.generateCanonicalGenesis((this.blockchain).genesisState()) } else { throw new Error( 'cannot activate genesis state: blockchain object has no `genesisState` method' @@ -175,11 +159,11 @@ export class VM { } if (this._opts.activatePrecompiles === true && typeof this._opts.stateManager === 'undefined') { - await this.eei.checkpoint() + await this.stateManager.checkpoint() // put 1 wei in each of the precompiles in order to make the accounts non-empty and thus not have them deduct `callNewAccount` gas. for (const [addressStr] of getActivePrecompiles(this._common)) { const address = new Address(hexToBytes(addressStr)) - let account = await this.eei.getAccount(address) + let account = await this.stateManager.getAccount(address) // Only do this if it is not overridden in genesis // Note: in the case that custom genesis has storage fields, this is preserved if (account === undefined) { @@ -188,10 +172,10 @@ export class VM { balance: 1, storageRoot: account.storageRoot, }) - await this.eei.putAccount(address, newAccount) + await this.stateManager.putAccount(address, newAccount) } } - await this.eei.commit() + await this.stateManager.commit() } this._isInitialized = true } @@ -247,17 +231,19 @@ export class VM { async copy(): Promise { const common = this._common.copy() common.setHardfork(this._common.hardfork()) - const eeiCopy = new EEI(this.stateManager.copy(), common, this.blockchain.copy()) + const blockchain = this.blockchain.copy() + const stateManager = this.stateManager.copy() const evmOpts = { ...(this.evm as any)._optsCached, common, - eei: eeiCopy, + blockchain, + stateManager, } const evmCopy = new EVM(evmOpts) return VM.create({ - stateManager: (eeiCopy as any)._stateManager, - blockchain: (eeiCopy as any)._blockchain, - common: (eeiCopy as any)._common, + stateManager, + blockchain: this.blockchain, + common, evm: evmCopy, hardforkByBlockNumber: this._hardforkByBlockNumber ? true : undefined, hardforkByTTD: this._hardforkByTTD, diff --git a/packages/vm/test/api/EIPs/eip-3529.spec.ts b/packages/vm/test/api/EIPs/eip-3529.spec.ts index c242e4df51..2278bc1bea 100644 --- a/packages/vm/test/api/EIPs/eip-3529.spec.ts +++ b/packages/vm/test/api/EIPs/eip-3529.spec.ts @@ -139,7 +139,7 @@ tape('EIP-3529 tests', (t) => { ) await vm.stateManager.getContractStorage(address, key) - vm.eei.addWarmedStorage(address.toBytes(), key) + vm.stateManager.addWarmedStorage(address.bytes, key) await vm.evm.runCode!({ code, @@ -153,7 +153,7 @@ tape('EIP-3529 tests', (t) => { st.equal(gasUsed, BigInt(testCase.usedGas), 'correct used gas') // clear the storage cache, otherwise next test will use current original value - vm.eei.clearOriginalStorageCache() + vm.stateManager.clearOriginalStorageCache() } st.end() diff --git a/packages/vm/test/api/EIPs/eip-4895-withdrawals.spec.ts b/packages/vm/test/api/EIPs/eip-4895-withdrawals.spec.ts index d1009c6fe9..efb7a5fdb3 100644 --- a/packages/vm/test/api/EIPs/eip-4895-withdrawals.spec.ts +++ b/packages/vm/test/api/EIPs/eip-4895-withdrawals.spec.ts @@ -4,7 +4,7 @@ import { Chain, Common, Hardfork } from '@ethereumjs/common' import { decode } from '@ethereumjs/rlp' import { FeeMarketEIP1559Transaction } from '@ethereumjs/tx' import { Account, Address, GWEI_TO_WEI, KECCAK256_RLP, Withdrawal, zeros } from '@ethereumjs/util' -import { bytesToHex, hexToBytes } from 'ethereum-cryptography/utils' +import { bytesToHex, hexToBytes, toHex } from 'ethereum-cryptography/utils' import * as tape from 'tape' import genesisJSON = require('../../../../client/test/testdata/geth-genesis/withdrawals.json') @@ -118,8 +118,8 @@ tape('EIP4895 tests', (t) => { t.test('EIP4895: state updation should exclude 0 amount updates', async (st) => { const vm = await VM.create({ common }) - await vm.eei.generateCanonicalGenesis(parseGethGenesisState(genesisJSON)) - const preState = bytesToHex(await vm.eei.getStateRoot()) + await vm.stateManager.generateCanonicalGenesis(parseGethGenesisState(genesisJSON)) + const preState = toHex(await vm.stateManager.getStateRoot()) st.equal( preState, 'ca3149fa9e37db08d1cd49c9061db1002ef1cd58db2210f2115c8c989b2bdf45', @@ -147,7 +147,7 @@ tape('EIP4895 tests', (t) => { }, { common: vm._common } ) - postState = bytesToHex(await vm.eei.getStateRoot()) + postState = toHex(await vm.stateManager.getStateRoot()) await vm.runBlock({ block, generate: true }) st.equal( @@ -170,7 +170,7 @@ tape('EIP4895 tests', (t) => { { common: vm._common } ) await vm.runBlock({ block, generate: true }) - postState = bytesToHex(await vm.eei.getStateRoot()) + postState = toHex(await vm.stateManager.getStateRoot()) st.equal( postState, '23eadd91fca55c0e14034e4d63b2b3ed43f2e807b6bf4d276b784ac245e7fa3f', @@ -197,7 +197,7 @@ tape('EIP4895 tests', (t) => { 'correct state root should be generated' ) const vm = await VM.create({ common, blockchain }) - await vm.eei.generateCanonicalGenesis(parseGethGenesisState(genesisJSON)) + await vm.stateManager.generateCanonicalGenesis(parseGethGenesisState(genesisJSON)) const vmCopy = await vm.copy() const gethBlockBufferArray = decode(hexToBytes(gethWithdrawals8BlockRlp)) diff --git a/packages/vm/test/api/buildBlock.spec.ts b/packages/vm/test/api/buildBlock.spec.ts index aa2420a452..3a4ab5743a 100644 --- a/packages/vm/test/api/buildBlock.spec.ts +++ b/packages/vm/test/api/buildBlock.spec.ts @@ -149,7 +149,7 @@ tape('BlockBuilder', async (t) => { const vm = await VM.create({ common, blockchain }) // add balance for tx - await vm.eei.putAccount(signer.address, Account.fromAccountData({ balance: 100000 })) + await vm.stateManager.putAccount(signer.address, Account.fromAccountData({ balance: 100000 })) const blockBuilder = await vm.buildBlock({ parentBlock: genesisBlock, diff --git a/packages/vm/test/api/eei.spec.ts b/packages/vm/test/api/eei.spec.ts deleted file mode 100644 index 0d5609ed3e..0000000000 --- a/packages/vm/test/api/eei.spec.ts +++ /dev/null @@ -1,115 +0,0 @@ -import { Blockchain } from '@ethereumjs/blockchain' -import { Common } from '@ethereumjs/common' -import { EVM } from '@ethereumjs/evm' -import { DefaultStateManager as StateManager } from '@ethereumjs/statemanager' -import { Account, Address } from '@ethereumjs/util' -import { hexToBytes } from 'ethereum-cryptography/utils' -import * as tape from 'tape' - -import { VM } from '../../src' -import { EEI } from '../../src/eei/eei' - -const ZeroAddress = Address.zero() - -tape('EEI.copy()', async (t) => { - const eei = new EEI( - new StateManager(), - new Common({ chain: 'mainnet', hardfork: 'shanghai' }), - await Blockchain.create() - ) - const nonEmptyAccount = Account.fromAccountData({ nonce: 1 }) - await eei.putAccount(ZeroAddress, nonEmptyAccount) - await eei.checkpoint() - await eei.commit() - const copy = eei.copy() - t.equal( - (eei as any)._common.hardfork(), - (copy as any)._common.hardfork(), - 'copied EEI should have the same hardfork' - ) - t.equal( - (await copy.getAccount(ZeroAddress))!.nonce, - (await eei.getAccount(ZeroAddress))!.nonce, - 'copy should have same State data' - ) -}) - -tape('EEI', (t) => { - t.test('should return false on non-existing accounts', async (st) => { - const eei = new EEI( - new StateManager(), - new Common({ chain: 'mainnet' }), - await Blockchain.create() - ) // create a dummy EEI (no VM, no EVM, etc.) - st.notOk(await eei.accountExists(ZeroAddress)) - st.ok(await eei.accountIsEmptyOrNonExistent(ZeroAddress)) - st.end() - }) - - t.test( - 'should return false on non-existing accounts which once existed in state but are now gone', - async (st) => { - const eei = new EEI( - new StateManager(), - new Common({ chain: 'mainnet' }), - await Blockchain.create() - ) // create a dummy EEI (no VM, no EVM, etc.) - // create empty account - await eei.putAccount(ZeroAddress, new Account()) - st.ok(await eei.accountExists(ZeroAddress)) - st.ok(await eei.accountIsEmptyOrNonExistent(ZeroAddress)) - // now put a non-empty account - const nonEmptyAccount = Account.fromAccountData({ nonce: 1 }) - await eei.putAccount(ZeroAddress, nonEmptyAccount) - st.ok(await eei.accountExists(ZeroAddress)) - st.notOk(await eei.accountIsEmptyOrNonExistent(ZeroAddress)) - st.end() - } - ) - - t.test('should return true on existing accounts', async (st) => { - const eei = new EEI( - new StateManager(), - new Common({ chain: 'mainnet' }), - await Blockchain.create() - ) // create a dummy EEI (no VM, no EVM, etc.) - // create empty account - await eei.putAccount(ZeroAddress, new Account()) - st.ok(await eei.accountExists(ZeroAddress)) // sanity check: account exists before we delete it - st.ok(await eei.accountIsEmptyOrNonExistent(ZeroAddress)) // it is obviously empty - await eei.deleteAccount(ZeroAddress) // delete the account - st.notOk(await eei.accountExists(ZeroAddress)) // account should not exist - st.ok(await eei.accountIsEmptyOrNonExistent(ZeroAddress)) // account is empty - st.end() - }) - - t.test('eei should return consistent values in vm/evm', async (st) => { - const eei = new EEI( - new StateManager(), - new Common({ chain: 'mainnet' }), - await Blockchain.create() - ) - const evm = new EVM({ eei }) - try { - await VM.create({ eei, evm }) - st.fail('should have thrown') - } catch (err: any) { - st.equal( - err.message, - 'cannot specify EEI if EVM opt provided', - 'throws when EEI and EVM opts are provided' - ) - } - - const address = new Address(hexToBytes('02E815899482f27C899fB266319dE7cc97F72E87')) - void eei.putAccount(address, Account.fromAccountData({ nonce: 5, balance: '0x123' })) - const vm = await VM.create({ evm }) - const accountFromEEI = await vm.eei.getAccount(address) - const accountFromEVM = await vm.evm.eei.getAccount(address) - st.equal( - accountFromEEI!.balance, - accountFromEVM!.balance, - 'vm.eei and evm.eei produce the same accounts' - ) - }) -}) diff --git a/packages/vm/test/api/runBlock.spec.ts b/packages/vm/test/api/runBlock.spec.ts index 85709e3cc2..1025e19789 100644 --- a/packages/vm/test/api/runBlock.spec.ts +++ b/packages/vm/test/api/runBlock.spec.ts @@ -38,7 +38,7 @@ tape('runBlock() -> successful API parameter usage', async (t) => { const block = Block.fromRLPSerializedBlock(blockRlp, { common }) //@ts-ignore - await setupPreConditions(vm.eei, testData) + await setupPreConditions(vm.stateManager, testData) st.deepEquals( //@ts-ignore @@ -66,7 +66,7 @@ tape('runBlock() -> successful API parameter usage', async (t) => { const testData = require('./testdata/uncleData.json') //@ts-ignore - await setupPreConditions(vm.eei, testData) + await setupPreConditions(vm.stateManager, testData) const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.London }) const block1Rlp = toBytes(testData.blocks[0].rlp) @@ -291,7 +291,7 @@ tape('runBlock() -> runtime behavior', async (t) => { block1[0][12] = utf8ToBytes('dao-hard-fork') const block = Block.fromValuesArray(block1, { common }) // @ts-ignore - await setupPreConditions(vm.eei, testData) + await setupPreConditions(vm.stateManager, testData) // fill two original DAO child-contracts with funds and the recovery account with funds in order to verify that the balance gets summed correctly const fundBalance1 = BigInt('0x1111') @@ -319,9 +319,11 @@ tape('runBlock() -> runtime behavior', async (t) => { generate: true, }) - const DAOFundedContractAccount1 = await vm.stateManager.getAccount(DAOFundedContractAddress1) + const DAOFundedContractAccount1 = + (await vm.stateManager.getAccount(DAOFundedContractAddress1)) ?? new Account() t.equals(DAOFundedContractAccount1!.balance, BigInt(0)) // verify our funded account now has 0 balance - const DAOFundedContractAccount2 = await vm.stateManager.getAccount(DAOFundedContractAddress2) + const DAOFundedContractAccount2 = + (await vm.stateManager.getAccount(DAOFundedContractAddress2)) ?? new Account() t.equals(DAOFundedContractAccount2!.balance, BigInt(0)) // verify our funded account now has 0 balance const DAORefundAccount = await vm.stateManager.getAccount(DAORefundAddress) @@ -422,7 +424,7 @@ async function runWithHf(hardfork: string) { const block = Block.fromRLPSerializedBlock(blockRlp, { common }) // @ts-ignore - await setupPreConditions(vm.eei, testData) + await setupPreConditions(vm.stateManager, testData) const res = await vm.runBlock({ block, @@ -467,7 +469,7 @@ tape('runBlock() -> tx types', async (t) => { } //@ts-ignore - await setupPreConditions(vm.eei, testData) + await setupPreConditions(vm.stateManager, testData) const res = await vm.runBlock({ block, diff --git a/packages/vm/test/api/runTx.spec.ts b/packages/vm/test/api/runTx.spec.ts index 6dff8e167e..6ed3e29ad9 100644 --- a/packages/vm/test/api/runTx.spec.ts +++ b/packages/vm/test/api/runTx.spec.ts @@ -43,7 +43,7 @@ tape('runTx() -> successful API parameter usage', async (t) => { const caller = tx.getSenderAddress() const acc = createAccount() - await vm.eei.putAccount(caller, acc) + await vm.stateManager.putAccount(caller, acc) let block if (vm._common.consensusType() === 'poa') { // Setup block with correct extraData for POA @@ -82,7 +82,7 @@ tape('runTx() -> successful API parameter usage', async (t) => { const tx = getTransaction(vm._common, 0, true) const caller = tx.getSenderAddress() const acc = createAccount() - await vm.eei.putAccount(caller, acc) + await vm.stateManager.putAccount(caller, acc) const block = Block.fromBlockData({}, { common: vm._common.copy() }) await vm.runTx({ tx, block }) st.pass('matched hardfork should run without throwing') @@ -98,7 +98,7 @@ tape('runTx() -> successful API parameter usage', async (t) => { const tx = getTransaction(vm._common, 0, true) const caller = tx.getSenderAddress() const acc = createAccount() - await vm.eei.putAccount(caller, acc) + await vm.stateManager.putAccount(caller, acc) const block = Block.fromBlockData({}, { common: vm._common.copy() }) block._common.setHardfork(Hardfork.Paris) @@ -143,7 +143,7 @@ tape('runTx() -> successful API parameter usage', async (t) => { const tx = getTransaction(vm._common, 0, true) const caller = tx.getSenderAddress() const acc = createAccount() - await vm.eei.putAccount(caller, acc) + await vm.stateManager.putAccount(caller, acc) const block = Block.fromBlockData({}, { common: vm._common.copy() }) tx.common.setHardfork(Hardfork.GrayGlacier) @@ -166,7 +166,7 @@ tape('runTx() -> successful API parameter usage', async (t) => { const caller = tx.getSenderAddress() const acc = createAccount() - await vm.eei.putAccount(caller, acc) + await vm.stateManager.putAccount(caller, acc) const blockGasUsed = BigInt(1000) const res = await vm.runTx({ tx, blockGasUsed }) @@ -186,7 +186,7 @@ tape('runTx() -> successful API parameter usage', async (t) => { const caller = tx.getSenderAddress() const acc = createAccount() - await vm.eei.putAccount(caller, acc) + await vm.stateManager.putAccount(caller, acc) const res = await vm.runTx({ tx }) t.true( @@ -209,8 +209,8 @@ tape('runTx() -> successful API parameter usage', async (t) => { const address = Address.fromPrivateKey(privateKey) const initialBalance = BigInt(10) ** BigInt(18) - const account = await vm.eei.getAccount(address) - await vm.eei.putAccount( + const account = await vm.stateManager.getAccount(address) + await vm.stateManager.putAccount( address, Account.fromAccountData({ ...account, balance: initialBalance }) ) @@ -248,7 +248,7 @@ tape('runTx() -> successful API parameter usage', async (t) => { skipBlockGasLimitValidation: true, }) - const coinbaseAccount = await vm.eei.getAccount(new Address(coinbase)) + const coinbaseAccount = await vm.stateManager.getAccount(new Address(coinbase)) // calculate expected coinbase balance const baseFee = block.header.baseFeePerGas! @@ -293,7 +293,7 @@ tape('runTx() -> API parameter usage/data errors', (t) => { const caller = tx.getSenderAddress() const acc = createAccount() - await vm.eei.putAccount(caller, acc) + await vm.stateManager.putAccount(caller, acc) try { await vm.runTx({ tx, skipHardForkValidation: true }) @@ -316,7 +316,7 @@ tape('runTx() -> API parameter usage/data errors', (t) => { const caller = tx.getSenderAddress() const acc = createAccount() - await vm.eei.putAccount(caller, acc) + await vm.stateManager.putAccount(caller, acc) const res = await vm.runTx({ tx, reportAccessList: true }) t.true( @@ -359,7 +359,7 @@ tape('runTx() -> API parameter usage/data errors', (t) => { const address = tx.getSenderAddress() tx = Object.create(tx) const maxCost: bigint = tx.gasLimit * tx.maxFeePerGas - await vm.eei.putAccount(address, createAccount(BigInt(0), maxCost - BigInt(1))) + await vm.stateManager.putAccount(address, createAccount(BigInt(0), maxCost - BigInt(1))) try { await vm.runTx({ tx }) t.fail('should throw error') @@ -367,7 +367,7 @@ tape('runTx() -> API parameter usage/data errors', (t) => { t.ok(e.message.toLowerCase().includes('max cost'), `should fail if max cost exceeds balance`) } // set sufficient balance - await vm.eei.putAccount(address, createAccount(BigInt(0), maxCost)) + await vm.stateManager.putAccount(address, createAccount(BigInt(0), maxCost)) const res = await vm.runTx({ tx }) t.ok(res, 'should pass if balance is sufficient') @@ -378,13 +378,13 @@ tape('runTx() -> API parameter usage/data errors', (t) => { const vm = await VM.create({ common }) const tx = getTransaction(common, 2, true, '0x0', false) const address = tx.getSenderAddress() - await vm.eei.putAccount(address, new Account()) - const account = await vm.eei.getAccount(address) + await vm.stateManager.putAccount(address, new Account()) + const account = await vm.stateManager.getAccount(address) account!.balance = BigInt(9000000) // This is the maxFeePerGas multiplied with the gasLimit of 90000 - await vm.eei.putAccount(address, account!) + await vm.stateManager.putAccount(address, account!) await vm.runTx({ tx }) account!.balance = BigInt(9000000) - await vm.eei.putAccount(address, account!) + await vm.stateManager.putAccount(address, account!) const tx2 = getTransaction(common, 2, true, '0x64', false) // Send 100 wei; now balance < maxFeePerGas*gasLimit + callvalue try { await vm.runTx({ tx: tx2 }) @@ -399,11 +399,11 @@ tape('runTx() -> API parameter usage/data errors', (t) => { const vm = await VM.create({ common }) const tx = getTransaction(common, 2, true, '0x0', false) const address = tx.getSenderAddress() - await vm.eei.putAccount(address, new Account()) - const account = await vm.eei.getAccount(address) + await vm.stateManager.putAccount(address, new Account()) + const account = await vm.stateManager.getAccount(address) account!.balance = BigInt(9000000) // This is the maxFeePerGas multiplied with the gasLimit of 90000 account!.nonce = BigInt(1) - await vm.eei.putAccount(address, account!) + await vm.stateManager.putAccount(address, account!) try { await vm.runTx({ tx }) t.fail('cannot reach this') @@ -450,8 +450,8 @@ tape('runTx() -> runtime behavior', async (t) => { */ const code = hexToBytes('6001600055FE') const address = new Address(hexToBytes('00000000000000000000000000000000000000ff')) - await vm.eei.putContractCode(address, code) - await vm.eei.putContractStorage( + await vm.stateManager.putContractCode(address, code) + await vm.stateManager.putContractStorage( address, hexToBytes('00'.repeat(32)), hexToBytes('00'.repeat(31) + '01') @@ -469,12 +469,12 @@ tape('runTx() -> runtime behavior', async (t) => { } const tx = TransactionFactory.fromTxData(txParams, { common }).sign(privateKey) - await vm.eei.putAccount(tx.getSenderAddress(), createAccount()) + await vm.stateManager.putAccount(tx.getSenderAddress(), createAccount()) await vm.runTx({ tx }) // this tx will fail, but we have to ensure that the cache is cleared t.equal( - (vm.eei)._originalStorageCache.size, + (vm.stateManager)._originalStorageCache.size, 0, `should clear storage cache after every ${txType.name}` ) @@ -491,10 +491,10 @@ tape('runTx() -> runtime errors', async (t) => { const caller = tx.getSenderAddress() const from = createAccount() - await vm.eei.putAccount(caller, from) + await vm.stateManager.putAccount(caller, from) const to = createAccount(BigInt(0), MAX_INTEGER) - await vm.eei.putAccount(tx.to!, to) + await vm.stateManager.putAccount(tx.to!, to) const res = await vm.runTx({ tx }) @@ -503,7 +503,11 @@ tape('runTx() -> runtime errors', async (t) => { 'value overflow', `result should have 'value overflow' error set (${txType.name})` ) - t.equal((vm.eei)._checkpointCount, 0, `checkpoint count should be 0 (${txType.name})`) + t.equal( + (vm.stateManager)._checkpointCount, + 0, + `checkpoint count should be 0 (${txType.name})` + ) } t.end() }) @@ -515,11 +519,11 @@ tape('runTx() -> runtime errors', async (t) => { const caller = tx.getSenderAddress() const from = createAccount() - await vm.eei.putAccount(caller, from) + await vm.stateManager.putAccount(caller, from) const contractAddress = new Address(hexToBytes('61de9dc6f6cff1df2809480882cfd3c2364b28f7')) const to = createAccount(BigInt(0), MAX_INTEGER) - await vm.eei.putAccount(contractAddress, to) + await vm.stateManager.putAccount(contractAddress, to) const res = await vm.runTx({ tx }) @@ -528,7 +532,11 @@ tape('runTx() -> runtime errors', async (t) => { 'value overflow', `result should have 'value overflow' error set (${txType.name})` ) - t.equal((vm.eei)._checkpointCount, 0, `checkpoint count should be 0 (${txType.name})`) + t.equal( + (vm.stateManager)._checkpointCount, + 0, + `checkpoint count should be 0 (${txType.name})` + ) } t.end() }) @@ -543,7 +551,7 @@ tape('runTx() -> API return values', async (t) => { const caller = tx.getSenderAddress() const acc = createAccount() - await vm.eei.putAccount(caller, acc) + await vm.stateManager.putAccount(caller, acc) const res = await vm.runTx({ tx }) t.equal( @@ -573,7 +581,7 @@ tape('runTx() -> API return values', async (t) => { const caller = tx.getSenderAddress() const acc = createAccount() - await vm.eei.putAccount(caller, acc) + await vm.stateManager.putAccount(caller, acc) const res = await vm.runTx({ tx }) @@ -654,16 +662,16 @@ tape('runTx() -> consensus bugs', async (t) => { const vm = await VM.create({ common }) const addr = Address.fromString('0xd3563d8f19a85c95beab50901fd59ca4de69174c') - await vm.eei.putAccount(addr, new Account()) - const acc = await vm.eei.getAccount(addr) + await vm.stateManager.putAccount(addr, new Account()) + const acc = await vm.stateManager.getAccount(addr) acc!.balance = beforeBalance acc!.nonce = BigInt(2) - await vm.eei.putAccount(addr, acc!) + await vm.stateManager.putAccount(addr, acc!) const tx = Transaction.fromTxData(txData, { common }) await vm.runTx({ tx }) - const newBalance = (await vm.eei.getAccount(addr))!.balance + const newBalance = (await vm.stateManager.getAccount(addr))!.balance t.equals(newBalance, afterBalance) t.end() }) @@ -693,10 +701,10 @@ tape('runTx() -> consensus bugs', async (t) => { const vm = await VM.create({ common }) const addr = Address.fromPrivateKey(pkey) - await vm.eei.putAccount(addr, new Account()) - const acc = await vm.eei.getAccount(addr) + await vm.stateManager.putAccount(addr, new Account()) + const acc = await vm.stateManager.getAccount(addr) acc!.balance = BigInt(10000000000000) - await vm.eei.putAccount(addr, acc!) + await vm.stateManager.putAccount(addr, acc!) const tx = FeeMarketEIP1559Transaction.fromTxData(txData, { common }).sign(pkey) @@ -791,10 +799,10 @@ tape( }).sign(pkey) const addr = Address.fromPrivateKey(pkey) - await vm.eei.putAccount(addr, new Account()) - const acc = await vm.eei.getAccount(addr) + await vm.stateManager.putAccount(addr, new Account()) + const acc = await vm.stateManager.getAccount(addr) acc!.balance = BigInt(tx.gasLimit * tx.gasPrice) - await vm.eei.putAccount(addr, acc!) + await vm.stateManager.putAccount(addr, acc!) await vm.runTx({ tx, skipHardForkValidation: true }) const hash = await vm.stateManager.getContractStorage(codeAddr, hexToBytes('00'.repeat(32))) @@ -830,10 +838,10 @@ tape( }).sign(pkey) const addr = Address.fromPrivateKey(pkey) - await vm.eei.putAccount(addr, new Account()) - const acc = await vm.eei.getAccount(addr) + await vm.stateManager.putAccount(addr, new Account()) + const acc = await vm.stateManager.getAccount(addr) acc!.balance = BigInt(tx.gasLimit * tx.gasPrice + tx.value) - await vm.eei.putAccount(addr, acc!) + await vm.stateManager.putAccount(addr, acc!) t.equals( (await vm.runTx({ tx, skipHardForkValidation: true })).totalGasSpent, BigInt(27818), @@ -866,10 +874,10 @@ tape( }).sign(pkey) const addr = Address.fromPrivateKey(pkey) - await vm.eei.putAccount(addr, new Account()) - const acc = await vm.eei.getAccount(addr) + await vm.stateManager.putAccount(addr, new Account()) + const acc = await vm.stateManager.getAccount(addr) acc!.balance = BigInt(tx.gasLimit * tx.gasPrice + tx.value) - await vm.eei.putAccount(addr, acc!) + await vm.stateManager.putAccount(addr, acc!) t.equals( (await vm.runTx({ tx, skipHardForkValidation: true })).totalGasSpent, BigInt(13001), diff --git a/packages/vm/test/api/state/accountExists.spec.ts b/packages/vm/test/api/state/accountExists.spec.ts index 8c349f7522..062b92cb2b 100644 --- a/packages/vm/test/api/state/accountExists.spec.ts +++ b/packages/vm/test/api/state/accountExists.spec.ts @@ -71,7 +71,7 @@ tape( await vm.stateManager.putAccount(emptyAddress, new Account()) const emptyAccount = await vm.stateManager.getAccount(emptyAddress) //@ts-ignore - vm.stateManager._trie.put(toBytes(emptyAddress), emptyAccount.serialize()) + await vm.stateManager._trie.put(toBytes(emptyAddress), emptyAccount.serialize()) await vm.stateManager.putContractCode(contractAddress, hexToBytes(code)) // setup the contract code await vm.stateManager.putContractStorage( contractAddress, diff --git a/packages/vm/test/api/utils.ts b/packages/vm/test/api/utils.ts index 8e7c6c6afc..8cd52c9e92 100644 --- a/packages/vm/test/api/utils.ts +++ b/packages/vm/test/api/utils.ts @@ -18,9 +18,9 @@ export function createAccount(nonce = BigInt(0), balance = BigInt(0xfff384)) { export async function setBalance(vm: VM, address: Address, balance = BigInt(100000000)) { const account = createAccount(BigInt(0), balance) - await vm.eei.checkpoint() - await vm.eei.putAccount(address, account) - await vm.eei.commit() + await vm.stateManager.checkpoint() + await vm.stateManager.putAccount(address, account) + await vm.stateManager.commit() } export async function setupVM(opts: VMOpts & { genesisBlock?: Block } = {}) { @@ -41,10 +41,6 @@ export async function setupVM(opts: VMOpts & { genesisBlock?: Block } = {}) { return vm } -export async function getEEI() { - return (await setupVM()).eei -} - export function getTransaction( common: Common, txType = 0, diff --git a/packages/vm/test/retesteth/transition-child.ts b/packages/vm/test/retesteth/transition-child.ts index 694920e0f7..ffd7e45849 100644 --- a/packages/vm/test/retesteth/transition-child.ts +++ b/packages/vm/test/retesteth/transition-child.ts @@ -2,7 +2,7 @@ import { Block, BlockHeader } from '@ethereumjs/block' import { Blockchain } from '@ethereumjs/blockchain' import { RLP } from '@ethereumjs/rlp' import { Transaction, TransactionFactory } from '@ethereumjs/tx' -import { bytesToPrefixedHexString } from '@ethereumjs/util' +import { Account, bytesToPrefixedHexString } from '@ethereumjs/util' import { keccak256 } from 'ethereum-cryptography/keccak' import { hexToBytes } from 'ethereum-cryptography/utils' import { readFileSync, writeFileSync } from 'fs' @@ -59,13 +59,12 @@ async function runTransition(argsIn: any) { const genesis = Block.fromBlockData({ header: BlockHeader.fromHeaderData(genesisBlockData) }) blockchain = await Blockchain.create({ common, genesisBlock: genesis }) } - const vm = - blockchain !== undefined ? await VM.create({ common, blockchain }) : await VM.create({ common }) - await setupPreConditions(vm.eei, { pre: alloc }) + const vm = blockchain ? await VM.create({ common, blockchain }) : await VM.create({ common }) + await setupPreConditions(vm.stateManager, { pre: alloc }) const block = makeBlockFromEnv(inputEnv, { common }) - const acc = await vm.stateManager.getAccount(block.header.coinbase) + const acc = (await vm.stateManager.getAccount(block.header.coinbase)) ?? new Account() await vm.stateManager.putAccount(block.header.coinbase, acc) const txsData = RLP.decode(hexToBytes(rlpTxs.slice(2))) @@ -126,10 +125,10 @@ async function runTransition(argsIn: any) { const logsBloom = builder.logsBloom() const logsHash = keccak256(logsBloom) - await vm.eei.cleanupTouchedAccounts() + await vm.stateManager.cleanupTouchedAccounts() const output = { - stateRoot: bytesToPrefixedHexString(await vm.eei.getStateRoot()), + stateRoot: bytesToPrefixedHexString(await vm.stateManager.getStateRoot()), txRoot: bytesToPrefixedHexString(await builder.transactionsTrie()), receiptsRoot: bytesToPrefixedHexString(await builder.receiptTrie()), logsHash: bytesToPrefixedHexString(logsHash), diff --git a/packages/vm/test/tester/runners/BlockchainTestsRunner.ts b/packages/vm/test/tester/runners/BlockchainTestsRunner.ts index 98cc69a2fd..2ff3dfbe5b 100644 --- a/packages/vm/test/tester/runners/BlockchainTestsRunner.ts +++ b/packages/vm/test/tester/runners/BlockchainTestsRunner.ts @@ -34,15 +34,16 @@ export async function runBlockchainTest(options: any, testData: any, t: tape.Tes // fix for BlockchainTests/GeneralStateTests/stRandom/* testData.lastblockhash = stripHexPrefix(testData.lastblockhash) + let common = options.common.copy() as Common + common.setHardforkByBlockNumber(0) + let cacheDB = new Level('./.cachedb') let state = new Trie({ useKeyHashing: true }) let stateManager = new DefaultStateManager({ trie: state, + common, }) - let common = options.common.copy() as Common - common.setHardforkByBlockNumber(0) - let validatePow = false // Only run with block validation when sealEngine present in test file // and being set to Ethash PoW validation @@ -93,7 +94,7 @@ export async function runBlockchainTest(options: any, testData: any, t: tape.Tes }) // set up pre-state - await setupPreConditions(vm.eei, testData) + await setupPreConditions(vm.stateManager, testData) t.deepEquals(vm.stateManager._trie.root(), genesisBlock.header.stateRoot, 'correct pre stateRoot') diff --git a/packages/vm/test/tester/runners/GeneralStateTestsRunner.ts b/packages/vm/test/tester/runners/GeneralStateTestsRunner.ts index 1dd2912300..742f37e9f6 100644 --- a/packages/vm/test/tester/runners/GeneralStateTestsRunner.ts +++ b/packages/vm/test/tester/runners/GeneralStateTestsRunner.ts @@ -5,7 +5,6 @@ import { Trie } from '@ethereumjs/trie' import { Account, Address, bytesToHex, equalsBytes, toBytes } from '@ethereumjs/util' import { EVM } from '../../../../evm/src' -import { EEI } from '../../../src' import { makeBlockFromEnv, makeTx, setupPreConditions } from '../../util' import type { VM } from '../../../src' @@ -76,21 +75,22 @@ async function runTestCase(options: any, testData: any, t: tape.Test) { const begin = Date.now() // Copy the common object to not create long-lasting // references in memory which might prevent GC - let common = options.common.copy() + const common = options.common.copy() // Have to create a blockchain with empty block as genesisBlock for Merge // Otherwise mainnet genesis will throw since this has difficulty nonzero const genesisBlock = new Block(undefined, undefined, undefined, { common }) - let blockchain = await Blockchain.create({ genesisBlock, common }) - let state = new Trie({ useKeyHashing: true }) - let stateManager = new DefaultStateManager({ + const blockchain = await Blockchain.create({ genesisBlock, common }) + const state = new Trie({ useKeyHashing: true }) + const stateManager = new DefaultStateManager({ trie: state, + common, }) - let eei = new EEI(stateManager, common, blockchain) - let evm = new EVM({ common, eei }) - let vm = await VM.create({ state, stateManager, common, blockchain, evm }) - await setupPreConditions(vm.eei, testData) + const evm = new EVM({ common, stateManager, blockchain }) + const vm = await VM.create({ state, stateManager, common, blockchain, evm }) + + await setupPreConditions(vm.stateManager, testData) let execInfo = '' let tx @@ -103,8 +103,8 @@ async function runTestCase(options: any, testData: any, t: tape.Test) { // Even if no txs are ran, coinbase should always be created const coinbaseAddress = Address.fromString(testData.env.currentCoinbase) - const account = await (vm).eei.getAccount(coinbaseAddress) - await (vm).eei.putAccount(coinbaseAddress, account ?? new Account()) + const account = await (vm).stateManager.getAccount(coinbaseAddress) + await (vm).stateManager.putAccount(coinbaseAddress, account ?? new Account(), true) const stepHandler = (e: InterpreterStep) => { let hexStack = [] @@ -152,8 +152,8 @@ async function runTestCase(options: any, testData: any, t: tape.Test) { } // Cleanup touched accounts (this wipes coinbase if it is empty on HFs >= TangerineWhistle) - await (vm).eei.cleanupTouchedAccounts() - await (vm).eei.getStateRoot() // Ensure state root is updated (flush all changes to trie) + await (vm).stateManager.cleanupTouchedAccounts() + await (vm).stateManager.getStateRoot() // Ensure state root is updated (flush all changes to trie) const stateManagerStateRoot = vm.stateManager._trie.root() const testDataPostStateRoot = toBytes(testData.postStateRoot) @@ -168,7 +168,8 @@ async function runTestCase(options: any, testData: any, t: tape.Test) { vm.events.removeListener('afterTx', afterTxHandler) // @ts-ignore Explicitly delete objects for memory optimization (early GC) - common = blockchain = state = stateManager = eei = evm = vm = null // eslint-disable-line + // TODO FIXME + //common = blockchain = state = stateManager = evm = vm = null // eslint-disable-line return parseFloat(timeSpent) } diff --git a/packages/vm/test/util.ts b/packages/vm/test/util.ts index 64bc2487f4..5e7197bd5a 100644 --- a/packages/vm/test/util.ts +++ b/packages/vm/test/util.ts @@ -20,8 +20,8 @@ import { import { keccak256 } from 'ethereum-cryptography/keccak' import { bytesToHex, equalsBytes, hexToBytes } from 'ethereum-cryptography/utils' -import type { VmState } from '../src/eei/vmState' import type { BlockOptions } from '@ethereumjs/block' +import type { EVMStateManagerInterface } from '@ethereumjs/common' import type { TxOptions } from '@ethereumjs/tx' import type * as tape from 'tape' @@ -328,7 +328,7 @@ export function makeBlockFromEnv(env: any, opts?: BlockOptions): Block { * @param state - the state DB/trie * @param testData - JSON from tests repo */ -export async function setupPreConditions(state: VmState, testData: any) { +export async function setupPreConditions(state: EVMStateManagerInterface, testData: any) { await state.checkpoint() for (const addressStr of Object.keys(testData.pre)) { const { nonce, balance, code, storage } = testData.pre[addressStr] From ee0d44cbd53185caf53305492bfc41fd0c6aeff6 Mon Sep 17 00:00:00 2001 From: acolytec3 Date: Thu, 11 May 2023 13:08:36 -0400 Subject: [PATCH 37/53] Use `storageCache` in `ethersStateManager` (#2697) * Use storageCache in ethersStateManager * Lint * Address feedback --- package-lock.json | 26 ++++++----- .../statemanager/src/ethersStateManager.ts | 44 ++++++++----------- 2 files changed, 32 insertions(+), 38 deletions(-) diff --git a/package-lock.json b/package-lock.json index dbb9c85ec4..375ff709e0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17838,7 +17838,7 @@ "testdouble": "^3.17.2" }, "engines": { - "node": ">=14" + "node": ">=16" } }, "packages/blockchain": { @@ -17865,7 +17865,7 @@ "@types/level-errors": "^3.0.0" }, "engines": { - "node": ">=14" + "node": ">=16" } }, "packages/client": { @@ -17942,7 +17942,7 @@ "webpack-cli": "^4.8.0" }, "engines": { - "node": ">=14" + "node": ">=16" } }, "packages/client/node_modules/cliui": { @@ -18043,7 +18043,7 @@ "testdouble": "^3.8.2" }, "engines": { - "node": ">=14" + "node": ">=16" } }, "packages/devp2p/node_modules/ansi-styles": { @@ -18119,7 +18119,7 @@ "memory-level": "^1.0.0" }, "engines": { - "node": ">=14" + "node": ">=16" } }, "packages/evm": { @@ -18128,7 +18128,7 @@ "license": "MPL-2.0", "dependencies": { "@ethereumjs/common": "^3.1.1", - "@ethereumjs/tx": "^4.1.1", + "@ethereumjs/statemanager": "^1.0.4", "@ethereumjs/util": "^8.0.5", "debug": "^4.3.3", "ethereum-cryptography": "^1.1.2", @@ -18137,6 +18137,7 @@ }, "devDependencies": { "@ethereumjs/statemanager": "^1.0.4", + "@ethersproject/abi": "^5.0.12", "@types/benchmark": "^1.0.33", "@types/core-js": "^2.5.0", "@types/minimist": "^1.2.2", @@ -18150,7 +18151,7 @@ "solc": "^0.8.1" }, "engines": { - "node": ">=14" + "node": ">=16" } }, "packages/rlp": { @@ -18161,7 +18162,7 @@ "rlp": "bin/rlp" }, "engines": { - "node": ">=14" + "node": ">=16" } }, "packages/statemanager": { @@ -18224,7 +18225,7 @@ "micro-bmark": "0.2.0" }, "engines": { - "node": ">=14" + "node": ">=16" } }, "packages/trie/node_modules/readable-stream": { @@ -18258,7 +18259,7 @@ "testdouble": "^3.17.2" }, "engines": { - "node": ">=14" + "node": ">=16" }, "peerDependencies": { "c-kzg": "^2.0.4" @@ -18283,7 +18284,7 @@ "@types/secp256k1": "^4.0.1" }, "engines": { - "node": ">=14" + "node": ">=16" }, "peerDependencies": { "c-kzg": "^2.0.4" @@ -18335,7 +18336,7 @@ "typescript": "^4.4.2" }, "engines": { - "node": ">=14" + "node": ">=16" } }, "packages/vm/node_modules/brace-expansion": { @@ -19777,6 +19778,7 @@ "@ethereumjs/common": "^3.1.1", "@ethereumjs/statemanager": "^1.0.4", "@ethereumjs/util": "^8.0.5", + "@ethersproject/abi": "^5.0.12", "@types/benchmark": "^1.0.33", "@types/core-js": "^2.5.0", "@types/minimist": "^1.2.2", diff --git a/packages/statemanager/src/ethersStateManager.ts b/packages/statemanager/src/ethersStateManager.ts index 8a05158e2e..5e40097d6c 100644 --- a/packages/statemanager/src/ethersStateManager.ts +++ b/packages/statemanager/src/ethersStateManager.ts @@ -4,7 +4,7 @@ import { debug } from 'debug' import { keccak256 } from 'ethereum-cryptography/keccak' import { ethers } from 'ethers' -import { AccountCache, CacheType } from './cache' +import { AccountCache, CacheType, StorageCache } from './cache' import type { Proof } from '.' import type { AccountFields, StateManagerInterface, StorageDump } from '@ethereumjs/common' @@ -20,7 +20,7 @@ export interface EthersStateManagerOpts { export class EthersStateManager implements StateManagerInterface { private provider: ethers.providers.StaticJsonRpcProvider | ethers.providers.JsonRpcProvider private contractCache: Map - private storageCache: Map> + private storageCache: StorageCache private blockTag: string _accountCache: AccountCache @@ -36,8 +36,7 @@ export class EthersStateManager implements StateManagerInterface { this.blockTag = opts.blockTag === 'earliest' ? opts.blockTag : bigIntToHex(opts.blockTag) this.contractCache = new Map() - this.storageCache = new Map() - + this.storageCache = new StorageCache({ size: 10000, type: CacheType.LRU }) this._accountCache = new AccountCache({ size: 100000, type: CacheType.LRU }) } @@ -47,7 +46,7 @@ export class EthersStateManager implements StateManagerInterface { blockTag: BigInt(this.blockTag), }) ;(newState as any).contractCache = new Map(this.contractCache) - ;(newState as any).storageCache = new Map(this.storageCache) + ;(newState as any).storageCache = new StorageCache({ size: 10000, type: CacheType.LRU }) ;(newState as any)._accountCache = this._accountCache return newState } @@ -109,24 +108,22 @@ export class EthersStateManager implements StateManagerInterface { */ async getContractStorage(address: Address, key: Uint8Array): Promise { // Check storage slot in cache - const accountStorage: Map | undefined = this.storageCache.get( - address.toString() - ) - let storage: Uint8Array | string | undefined - if (accountStorage !== undefined) { - storage = accountStorage.get(bytesToHex(key)) - if (storage !== undefined) { - return storage - } + if (key.length !== 32) { + throw new Error('Storage key must be 32 bytes long') + } + + let value = this.storageCache!.get(address, key) + if (value !== undefined) { + return value } // Retrieve storage slot from provider if not found in cache - storage = await this.provider.getStorageAt( + const storage = await this.provider.getStorageAt( address.toString(), bytesToBigInt(key), this.blockTag ) - const value = toBytes(storage) + value = toBytes(storage) await this.putContractStorage(address, key, value) return value @@ -142,12 +139,7 @@ export class EthersStateManager implements StateManagerInterface { * If it is empty or filled with zeros, deletes the value. */ async putContractStorage(address: Address, key: Uint8Array, value: Uint8Array): Promise { - let accountStorage = this.storageCache.get(address.toString()) - if (accountStorage === undefined) { - this.storageCache.set(address.toString(), new Map()) - accountStorage = this.storageCache.get(address.toString()) - } - accountStorage?.set(bytesToHex(key), value) + this.storageCache.put(address, key, value) } /** @@ -155,7 +147,7 @@ export class EthersStateManager implements StateManagerInterface { * @param address - Address to clear the storage of */ async clearContractStorage(address: Address): Promise { - this.storageCache.delete(address.toString()) + this.storageCache.clearContractStorage(address) } /** @@ -166,10 +158,10 @@ export class EthersStateManager implements StateManagerInterface { * Both are represented as `0x` prefixed hex strings. */ dumpStorage(address: Address): Promise { - const addressStorage = this.storageCache.get(address.toString()) + const storageMap = this.storageCache._lruCache?.get(address.toString()) const dump: StorageDump = {} - if (addressStorage !== undefined) { - for (const slot of addressStorage) { + if (storageMap !== undefined) { + for (const slot of storageMap) { dump[slot[0]] = bytesToHex(slot[1]) } } From 355b03b0272f5150321ea9eafdd13c9c9f9b600b Mon Sep 17 00:00:00 2001 From: Gabriel Rocheleau Date: Fri, 12 May 2023 05:48:41 -0400 Subject: [PATCH 38/53] blockchain: remove level dependency from blockchain (#2669) * blockchain: remove level dependency from blockchain * util: refactor DB types from trie to util * util: make db interface generic * blockchain: remove abstract-level usage in favor of DB interface and MapDB * WIP removal of level DB stuff (#2673) Co-authored-by: Gabriel Rocheleau * Add correct value encoding for keys in level * Apply correct db interface typing * Fix level encoding for strings * More typing fixes * Fix batch value encoding * fix deprecated property usage * Replace level with mapdb in VM * move mapDB to util * Cleanup * Add key/value encodings back to interface * Remove level dependency from ethash * Add db ops to blockchain * remove unused imports * remove leveldb * update trie to use strings * Slight fixes * lint * fix trie tests * cast trie db as any * client: improve levelDB types and remove unnecessary typecasting * client: remove additional unnecessary typecasting * client: type issue --------- Co-authored-by: acolytec3 Co-authored-by: acolytec3 <17355484+acolytec3@users.noreply.github.com> --- package-lock.json | 20 +-- packages/blockchain/package.json | 4 +- packages/blockchain/src/blockchain.ts | 152 ++++++++---------- packages/blockchain/src/consensus/clique.ts | 93 ++++------- packages/blockchain/src/consensus/ethash.ts | 3 +- packages/blockchain/src/db/manager.ts | 137 +++++++++------- packages/blockchain/src/db/operation.ts | 20 ++- packages/blockchain/src/types.ts | 13 +- packages/blockchain/test/index.spec.ts | 15 +- packages/blockchain/test/util.ts | 27 +--- packages/client/bin/cli.ts | 3 +- packages/client/browser/index.ts | 3 +- packages/client/lib/blockchain/chain.ts | 8 +- packages/client/lib/config.ts | 2 +- packages/client/lib/execution/level.ts | 85 ++++++++-- packages/client/lib/miner/miner.ts | 3 +- .../lib/sync/fetcher/bytecodefetcher.ts | 2 +- packages/client/test/blockchain/chain.spec.ts | 17 +- .../getTransactionByBlockHashAndIndex.spec.ts | 2 +- packages/client/test/sim/simutils.ts | 3 +- packages/client/test/sim/snapsync.spec.ts | 2 +- packages/ethash/package.json | 4 +- packages/ethash/src/index.ts | 65 ++++---- packages/ethash/test/block.spec.ts | 5 +- packages/ethash/test/miner.spec.ts | 8 +- packages/trie/benchmarks/index.ts | 2 +- packages/trie/recipes/level-legacy.ts | 10 +- packages/trie/recipes/level.ts | 6 +- packages/trie/recipes/lmdb.ts | 8 +- packages/trie/src/db/checkpoint.ts | 61 ++++--- packages/trie/src/db/index.ts | 1 - packages/trie/src/db/map.ts | 45 ------ packages/trie/src/trie/trie.ts | 38 +++-- packages/trie/src/types.ts | 54 +------ packages/trie/test/db/checkpoint.spec.ts | 10 +- packages/trie/test/db/db.spec.ts | 8 +- packages/trie/test/proof/range.spec.ts | 7 +- packages/trie/test/stream.spec.ts | 2 +- packages/trie/test/trie/checkpoint.spec.ts | 8 +- packages/trie/test/trie/secure.spec.ts | 5 +- packages/trie/test/trie/trie.spec.ts | 22 +-- packages/util/src/db.ts | 82 ++++++++++ packages/util/src/index.ts | 6 + packages/util/src/mapDB.ts | 50 ++++++ packages/vm/package.json | 2 - packages/vm/test/api/runBlock.spec.ts | 5 +- packages/vm/test/api/utils.ts | 3 +- packages/vm/test/level.ts | 78 +++++++++ .../tester/runners/BlockchainTestsRunner.ts | 11 +- 49 files changed, 695 insertions(+), 525 deletions(-) delete mode 100644 packages/trie/src/db/map.ts create mode 100644 packages/util/src/db.ts create mode 100644 packages/util/src/mapDB.ts create mode 100644 packages/vm/test/level.ts diff --git a/package-lock.json b/package-lock.json index 375ff709e0..4967ee9850 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17853,12 +17853,10 @@ "@ethereumjs/trie": "^5.0.4", "@ethereumjs/tx": "^4.1.1", "@ethereumjs/util": "^8.0.5", - "abstract-level": "^1.0.3", "debug": "^4.3.3", "ethereum-cryptography": "^1.1.2", "level": "^8.0.0", - "lru-cache": "^7.18.3", - "memory-level": "^1.0.0" + "lru-cache": "^7.18.3" }, "devDependencies": { "@types/async": "^2.4.1", @@ -18110,13 +18108,11 @@ "@ethereumjs/block": "^4.2.1", "@ethereumjs/rlp": "^4.0.1", "@ethereumjs/util": "^8.0.5", - "abstract-level": "^1.0.3", "bigint-crypto-utils": "^3.0.23", "ethereum-cryptography": "^1.1.2" }, "devDependencies": { - "@ethereumjs/common": "^3.1.1", - "memory-level": "^1.0.0" + "@ethereumjs/common": "^3.1.1" }, "engines": { "node": ">=16" @@ -18322,8 +18318,6 @@ "@types/node-dir": "^0.0.34", "benchmark": "^2.1.4", "c-kzg": "^2.0.4", - "level": "^8.0.0", - "memory-level": "^1.0.0", "minimist": "^1.2.5", "node-dir": "^0.1.17", "nyc": "^15.1.0", @@ -19571,12 +19565,10 @@ "@ethereumjs/util": "^8.0.5", "@types/async": "^2.4.1", "@types/level-errors": "^3.0.0", - "abstract-level": "^1.0.3", "debug": "^4.3.3", "ethereum-cryptography": "^1.1.2", "level": "^8.0.0", - "lru-cache": "^7.18.3", - "memory-level": "^1.0.0" + "lru-cache": "^7.18.3" } }, "@ethereumjs/client": { @@ -19766,10 +19758,8 @@ "@ethereumjs/common": "^3.1.1", "@ethereumjs/rlp": "^4.0.1", "@ethereumjs/util": "^8.0.5", - "abstract-level": "^1.0.3", "bigint-crypto-utils": "^3.0.23", - "ethereum-cryptography": "^1.1.2", - "memory-level": "^1.0.0" + "ethereum-cryptography": "^1.1.2" } }, "@ethereumjs/evm": { @@ -19905,9 +19895,7 @@ "c-kzg": "^2.0.4", "debug": "^4.3.3", "ethereum-cryptography": "^1.1.2", - "level": "^8.0.0", "mcl-wasm": "^0.7.1", - "memory-level": "^1.0.0", "minimist": "^1.2.5", "node-dir": "^0.1.17", "nyc": "^15.1.0", diff --git a/packages/blockchain/package.json b/packages/blockchain/package.json index 7745f1a4a8..54feaa8aa7 100644 --- a/packages/blockchain/package.json +++ b/packages/blockchain/package.json @@ -45,12 +45,10 @@ "@ethereumjs/trie": "^5.0.4", "@ethereumjs/tx": "^4.1.1", "@ethereumjs/util": "^8.0.5", - "abstract-level": "^1.0.3", "debug": "^4.3.3", "ethereum-cryptography": "^1.1.2", "level": "^8.0.0", - "lru-cache": "^7.18.3", - "memory-level": "^1.0.0" + "lru-cache": "^7.18.3" }, "devDependencies": { "@types/async": "^2.4.1", diff --git a/packages/blockchain/src/blockchain.ts b/packages/blockchain/src/blockchain.ts index 0e1ae42477..2dd7a90bca 100644 --- a/packages/blockchain/src/blockchain.ts +++ b/packages/blockchain/src/blockchain.ts @@ -1,8 +1,13 @@ import { Block, BlockHeader } from '@ethereumjs/block' import { Chain, Common, ConsensusAlgorithm, ConsensusType, Hardfork } from '@ethereumjs/common' -import { KECCAK256_RLP, Lock, concatBytesNoTypeCheck } from '@ethereumjs/util' +import { + KECCAK256_RLP, + Lock, + MapDB, + bytesToPrefixedHexString, + concatBytesNoTypeCheck, +} from '@ethereumjs/util' import { bytesToHex, equalsBytes, hexToBytes } from 'ethereum-cryptography/utils' -import { MemoryLevel } from 'memory-level' import { CasperConsensus, CliqueConsensus, EthashConsensus } from './consensus' import { DBOp, DBSaveLookups, DBSetBlockOrHeader, DBSetHashToNumber, DBSetTD } from './db/helpers' @@ -16,15 +21,14 @@ import type { GenesisState } from './genesisStates' import type { BlockchainInterface, BlockchainOptions, OnBlock } from './types' import type { BlockData } from '@ethereumjs/block' import type { CliqueConfig } from '@ethereumjs/common' -import type { BigIntLike } from '@ethereumjs/util' -import type { AbstractLevel } from 'abstract-level' +import type { BigIntLike, DB, DBObject } from '@ethereumjs/util' /** * This class stores and interacts with blocks. */ export class Blockchain implements BlockchainInterface { consensus: Consensus - db: AbstractLevel + db: DB dbManager: DBManager private _genesisBlock?: Block /** The genesis block of this blockchain */ @@ -115,7 +119,8 @@ export class Blockchain implements BlockchainInterface { this._validateBlocks = opts.validateBlocks ?? true this._customGenesisState = opts.genesisState - this.db = opts.db ? opts.db : new MemoryLevel() + this.db = opts.db !== undefined ? opts.db : new MapDB() + this.dbManager = new DBManager(this.db, this._common) if (opts.consensus) { @@ -191,17 +196,13 @@ export class Blockchain implements BlockchainInterface { await this.consensus.setup({ blockchain: this }) if (this._isInitialized) return - let dbGenesisBlock - try { - const genesisHash = await this.dbManager.numberToHash(BigInt(0)) - dbGenesisBlock = await this.dbManager.getBlock(genesisHash) - } catch (error: any) { - if (error.code !== 'LEVEL_NOT_FOUND') { - throw error - } - } - if (!genesisBlock) { + let genesisHash = await this.dbManager.numberToHash(BigInt(0)) + + const dbGenesisBlock = + genesisHash !== undefined ? await this.dbManager.getBlock(genesisHash) : undefined + + if (genesisBlock === undefined) { let stateRoot if (this._common.chainId() === BigInt(1) && this._customGenesisState === undefined) { // For mainnet use the known genesis stateRoot to quicken setup @@ -214,13 +215,13 @@ export class Blockchain implements BlockchainInterface { // If the DB has a genesis block, then verify that the genesis block in the // DB is indeed the Genesis block generated or assigned. - if (dbGenesisBlock && !equalsBytes(genesisBlock.hash(), dbGenesisBlock.hash())) { + if (dbGenesisBlock !== undefined && !equalsBytes(genesisBlock.hash(), dbGenesisBlock.hash())) { throw new Error( 'The genesis block in the DB has a different hash than the provided genesis block.' ) } - const genesisHash = genesisBlock.hash() + genesisHash = genesisBlock.hash() if (!dbGenesisBlock) { // If there is no genesis block put the genesis block in the DB. @@ -239,37 +240,16 @@ export class Blockchain implements BlockchainInterface { this._genesisBlock = genesisBlock // load verified iterator heads - try { - const heads = await this.dbManager.getHeads() - this._heads = heads - } catch (error: any) { - if (error.code !== 'LEVEL_NOT_FOUND') { - throw error - } - this._heads = {} - } + const heads = await this.dbManager.getHeads() + this._heads = heads !== undefined ? heads : {} // load headerchain head - try { - const hash = await this.dbManager.getHeadHeader() - this._headHeaderHash = hash - } catch (error: any) { - if (error.code !== 'LEVEL_NOT_FOUND') { - throw error - } - this._headHeaderHash = genesisHash - } + let hash = await this.dbManager.getHeadHeader() + this._headHeaderHash = hash !== undefined ? hash : genesisHash // load blockchain head - try { - const hash = await this.dbManager.getHeadBlock() - this._headBlockHash = hash - } catch (error: any) { - if (error.code !== 'LEVEL_NOT_FOUND') { - throw error - } - this._headBlockHash = genesisHash - } + hash = await this.dbManager.getHeadBlock() + this._headBlockHash = hash !== undefined ? hash : genesisHash if (this._hardforkByHeadBlockNumber) { const latestHeader = await this._getHeader(this._headHeaderHash) @@ -423,6 +403,9 @@ export class Blockchain implements BlockchainInterface { async resetCanonicalHead(canonicalHead: bigint) { await this.runWithLock(async () => { const hash = await this.dbManager.numberToHash(canonicalHead) + if (hash === undefined) { + throw new Error(`no block for ${canonicalHead} found in DB`) + } const header = await this._getHeader(hash, canonicalHead) const td = await this.getParentTD(header) @@ -738,18 +721,16 @@ export class Blockchain implements BlockchainInterface { // in the `VM` if we encounter a `BLOCKHASH` opcode: then a bigint is used we // need to then read the block from the canonical chain Q: is this safe? We // know it is OK if we call it from the iterator... (runBlock) - try { - return await this.dbManager.getBlock(blockId) - } catch (error: any) { - if (error.code === 'LEVEL_NOT_FOUND') { - if (typeof blockId === 'object') { - error.message = `Block with hash ${bytesToHex(blockId)} not found in DB (NotFound)` - } else { - error.message = `Block number ${blockId} not found in DB (NotFound)` - } + const block = await this.dbManager.getBlock(blockId) + + if (block === undefined) { + if (typeof blockId === 'object') { + throw new Error(`Block with hash ${bytesToHex(blockId)} not found in DB`) + } else { + throw new Error(`Block number ${blockId} not found in DB`) } - throw error } + return block } /** @@ -758,6 +739,9 @@ export class Blockchain implements BlockchainInterface { public async getTotalDifficulty(hash: Uint8Array, number?: bigint): Promise { if (number === undefined) { number = await this.dbManager.hashToNumber(hash) + if (number === undefined) { + throw new Error(`Block with hash ${bytesToPrefixedHexString(hash)} not found in DB`) + } } return this.dbManager.getTotalDifficulty(hash, number) } @@ -794,12 +778,12 @@ export class Blockchain implements BlockchainInterface { let block try { block = await this.getBlock(blockId) - } catch (error: any) { - if (error.code !== 'LEVEL_NOT_FOUND') { - throw error - } - return + } catch (err: any) { + if (err.message.includes('not found in DB') === true) { + return + } else throw err } + i++ const nextBlockNumber = block.header.number + BigInt(reverse ? -1 : 1) if (i !== 0 && skip && i % (skip + 1) !== 0) { @@ -835,11 +819,12 @@ export class Blockchain implements BlockchainInterface { let number try { number = await this.dbManager.hashToNumber(hashes[mid]) - } catch (error: any) { - if (error.code !== 'LEVEL_NOT_FOUND') { - throw error - } + } catch (err: any) { + if (err.message.includes('not found in DB') === true) { + number = undefined + } else throw err } + if (number !== undefined) { min = mid + 1 } else { @@ -945,9 +930,9 @@ export class Blockchain implements BlockchainInterface { try { const childHeader = await this.getCanonicalHeader(blockNumber + BigInt(1)) await this._delChild(childHeader.hash(), childHeader.number, headHash, ops) - } catch (error: any) { - if (error.code !== 'LEVEL_NOT_FOUND') { - throw error + } catch (err: any) { + if (err.message.includes('not found in canonical chain') !== true) { + throw err } } } @@ -977,7 +962,8 @@ export class Blockchain implements BlockchainInterface { } let headBlockNumber = await this.dbManager.hashToNumber(headHash) - let nextBlockNumber = headBlockNumber + BigInt(1) + // `headBlockNumber` should always exist since it defaults to the genesis block + let nextBlockNumber = headBlockNumber! + BigInt(1) let blocksRanCounter = 0 let lastBlock: Block | undefined @@ -992,7 +978,7 @@ export class Blockchain implements BlockchainInterface { // If reorg has happened, the _heads must have been updated so lets reload the counters headHash = this._heads[name] ?? this.genesisBlock.hash() headBlockNumber = await this.dbManager.hashToNumber(headHash) - nextBlockNumber = headBlockNumber + BigInt(1) + nextBlockNumber = headBlockNumber! + BigInt(1) nextBlock = await this.getBlock(nextBlockNumber) } @@ -1025,7 +1011,7 @@ export class Blockchain implements BlockchainInterface { // Successful execution of onBlock, move the head pointer blocksRanCounter++ } catch (error: any) { - if (error.code === 'LEVEL_NOT_FOUND') { + if ((error.message as string).includes('not found in DB')) { break } else { throw error @@ -1199,13 +1185,9 @@ export class Blockchain implements BlockchainInterface { staleHeadBlock = true } - try { - header = await this._getHeader(header.parentHash, --currentNumber) - } catch (error: any) { + header = await this._getHeader(header.parentHash, --currentNumber) + if (header === undefined) { staleHeads = [] - if (error.code !== 'LEVEL_NOT_FOUND') { - throw error - } break } } @@ -1259,6 +1241,8 @@ export class Blockchain implements BlockchainInterface { private async _getHeader(hash: Uint8Array, number?: bigint) { if (number === undefined) { number = await this.dbManager.hashToNumber(hash) + if (number === undefined) + throw new Error(`no header for ${bytesToPrefixedHexString(hash)} found in DB`) } return this.dbManager.getHeader(hash, number) } @@ -1302,25 +1286,21 @@ export class Blockchain implements BlockchainInterface { */ async getCanonicalHeader(number: bigint) { const hash = await this.dbManager.numberToHash(number) + if (hash === undefined) { + throw new Error(`header with number ${number} not found in canonical chain`) + } return this._getHeader(hash, number) } /** * This method either returns a Uint8Array if there exists one in the DB or if it - * does not exist (DB throws a `NotFoundError`) then return false If DB throws + * does not exist then return false If DB throws * any other error, this function throws. * @param number */ async safeNumberToHash(number: bigint): Promise { - try { - const hash = await this.dbManager.numberToHash(number) - return hash - } catch (error: any) { - if (error.code !== 'LEVEL_NOT_FOUND') { - throw error - } - return false - } + const hash = await this.dbManager.numberToHash(number) + return hash !== undefined ? hash : false } /** diff --git a/packages/blockchain/src/consensus/clique.ts b/packages/blockchain/src/consensus/clique.ts index b89aa64fc4..83e6a7d212 100644 --- a/packages/blockchain/src/consensus/clique.ts +++ b/packages/blockchain/src/consensus/clique.ts @@ -25,11 +25,6 @@ export const CLIQUE_DIFF_INTURN = BigInt(2) // Block difficulty for out-of-turn signatures export const CLIQUE_DIFF_NOTURN = BigInt(1) -const DB_OPTS = { - keyEncoding: 'view', - valueEncoding: 'view', -} - // Clique Signer State type CliqueSignerState = [blockNumber: bigint, signers: Address[]] type CliqueLatestSignerStates = CliqueSignerState[] @@ -253,7 +248,7 @@ export class CliqueConsensus implements Consensus { bigIntToBytes(state[0]), state[1].map((a) => a.toBytes()), ]) - await this.blockchain!.db.put(CLIQUE_SIGNERS_KEY, RLP.encode(formatted), DB_OPTS) + await this.blockchain!.db.put(CLIQUE_SIGNERS_KEY, RLP.encode(formatted)) // Output active signers for debugging purposes if (signerState !== undefined) { let i = 0 @@ -414,7 +409,7 @@ export class CliqueConsensus implements Consensus { bigIntToBytes(v[0]), [v[1][0].toBytes(), v[1][1].toBytes(), v[1][2]], ]) - await this.blockchain!.db.put(CLIQUE_VOTES_KEY, RLP.encode(formatted), DB_OPTS) + await this.blockchain!.db.put(CLIQUE_VOTES_KEY, RLP.encode(formatted)) } /** @@ -523,7 +518,7 @@ export class CliqueConsensus implements Consensus { bigIntToBytes(b[0]), b[1].toBytes(), ]) - await this.blockchain!.db.put(CLIQUE_BLOCK_SIGNERS_SNAPSHOT_KEY, RLP.encode(formatted), DB_OPTS) + await this.blockchain!.db.put(CLIQUE_BLOCK_SIGNERS_SNAPSHOT_KEY, RLP.encode(formatted)) } /** @@ -531,23 +526,14 @@ export class CliqueConsensus implements Consensus { * @hidden */ private async getCliqueLatestSignerStates(): Promise { - try { - const signerStates = await this.blockchain!.db.get( - CLIQUE_SIGNERS_KEY, - DB_OPTS - ) - const states = RLP.decode(signerStates) as [Uint8Array, Uint8Array[]] - return states.map((state) => { - const blockNum = bytesToBigInt(state[0] as Uint8Array) - const addrs = (state[1]).map((bytes: Uint8Array) => new Address(bytes)) - return [blockNum, addrs] - }) as CliqueLatestSignerStates - } catch (error: any) { - if (error.code === 'LEVEL_NOT_FOUND') { - return [] - } - throw error - } + const signerStates = await this.blockchain!.db.get(CLIQUE_SIGNERS_KEY) + if (signerStates === undefined) return [] + const states = RLP.decode(signerStates as Uint8Array) as [Uint8Array, Uint8Array[]] + return states.map((state) => { + const blockNum = bytesToBigInt(state[0] as Uint8Array) + const addrs = (state[1]).map((bytes: Uint8Array) => new Address(bytes)) + return [blockNum, addrs] + }) as CliqueLatestSignerStates } /** @@ -555,25 +541,19 @@ export class CliqueConsensus implements Consensus { * @hidden */ private async getCliqueLatestVotes(): Promise { - try { - const signerVotes = await this.blockchain!.db.get( - CLIQUE_VOTES_KEY, - DB_OPTS - ) - const votes = RLP.decode(signerVotes) as [Uint8Array, [Uint8Array, Uint8Array, Uint8Array]] - return votes.map((vote) => { - const blockNum = bytesToBigInt(vote[0] as Uint8Array) - const signer = new Address((vote[1] as any)[0]) - const beneficiary = new Address((vote[1] as any)[1]) - const nonce = (vote[1] as any)[2] - return [blockNum, [signer, beneficiary, nonce]] - }) as CliqueLatestVotes - } catch (error: any) { - if (error.code === 'LEVEL_NOT_FOUND') { - return [] - } - throw error - } + const signerVotes = await this.blockchain!.db.get(CLIQUE_VOTES_KEY) + if (signerVotes === undefined) return [] + const votes = RLP.decode(signerVotes as Uint8Array) as [ + Uint8Array, + [Uint8Array, Uint8Array, Uint8Array] + ] + return votes.map((vote) => { + const blockNum = bytesToBigInt(vote[0] as Uint8Array) + const signer = new Address((vote[1] as any)[0]) + const beneficiary = new Address((vote[1] as any)[1]) + const nonce = (vote[1] as any)[2] + return [blockNum, [signer, beneficiary, nonce]] + }) as CliqueLatestVotes } /** @@ -581,23 +561,14 @@ export class CliqueConsensus implements Consensus { * @hidden */ private async getCliqueLatestBlockSigners(): Promise { - try { - const blockSigners = await this.blockchain!.db.get( - CLIQUE_BLOCK_SIGNERS_SNAPSHOT_KEY, - DB_OPTS - ) - const signers = RLP.decode(blockSigners) as [Uint8Array, Uint8Array][] - return signers.map((s) => { - const blockNum = bytesToBigInt(s[0] as Uint8Array) - const signer = new Address(s[1] as any) - return [blockNum, signer] - }) as CliqueLatestBlockSigners - } catch (error: any) { - if (error.code === 'LEVEL_NOT_FOUND') { - return [] - } - throw error - } + const blockSigners = await this.blockchain!.db.get(CLIQUE_BLOCK_SIGNERS_SNAPSHOT_KEY) + if (blockSigners === undefined) return [] + const signers = RLP.decode(blockSigners as Uint8Array) as [Uint8Array, Uint8Array][] + return signers.map((s) => { + const blockNum = bytesToBigInt(s[0] as Uint8Array) + const signer = new Address(s[1] as any) + return [blockNum, signer] + }) as CliqueLatestBlockSigners } /** diff --git a/packages/blockchain/src/consensus/ethash.ts b/packages/blockchain/src/consensus/ethash.ts index 7a13245c13..76e5d6a7fa 100644 --- a/packages/blockchain/src/consensus/ethash.ts +++ b/packages/blockchain/src/consensus/ethash.ts @@ -4,7 +4,6 @@ import { Ethash } from '@ethereumjs/ethash' import type { Blockchain } from '..' import type { Consensus, ConsensusOptions } from './interface' import type { Block, BlockHeader } from '@ethereumjs/block' -import type { EthashCacheDB } from '@ethereumjs/ethash' /** * This class encapsulates Ethash-related consensus functionality when used with the Blockchain class. @@ -45,7 +44,7 @@ export class EthashConsensus implements Consensus { public async genesisInit(): Promise {} public async setup({ blockchain }: ConsensusOptions): Promise { this.blockchain = blockchain - this._ethash = new Ethash(this.blockchain.db as unknown as EthashCacheDB) + this._ethash = new Ethash(this.blockchain.db as any) } public async newBlock(): Promise {} } diff --git a/packages/blockchain/src/db/manager.ts b/packages/blockchain/src/db/manager.ts index 02aec83939..08cf567d4f 100644 --- a/packages/blockchain/src/db/manager.ts +++ b/packages/blockchain/src/db/manager.ts @@ -1,28 +1,21 @@ import { Block, BlockHeader, valuesArrayToHeaderData } from '@ethereumjs/block' import { RLP } from '@ethereumjs/rlp' -import { KECCAK256_RLP, KECCAK256_RLP_ARRAY, bytesToBigInt, equalsBytes } from '@ethereumjs/util' +import { + KECCAK256_RLP, + KECCAK256_RLP_ARRAY, + bytesToBigInt, + bytesToPrefixedHexString, + equalsBytes, +} from '@ethereumjs/util' import { hexToBytes } from 'ethereum-cryptography/utils' import { Cache } from './cache' import { DBOp, DBTarget } from './operation' -import type { DBOpData, DatabaseKey } from './operation' +import type { DatabaseKey } from './operation' import type { BlockBodyBytes, BlockBytes, BlockOptions } from '@ethereumjs/block' import type { Common } from '@ethereumjs/common' -import type { AbstractLevel } from 'abstract-level' - -class NotFoundError extends Error { - public code: string = 'LEVEL_NOT_FOUND' - - constructor(blockNumber: bigint) { - super(`Key ${blockNumber.toString()} was not found`) - - // `Error.captureStackTrace` is not defined in some browser contexts - if (typeof Error.captureStackTrace !== 'undefined') { - Error.captureStackTrace(this, this.constructor) - } - } -} +import type { BatchDBOp, DB, DBObject, DelBatch, PutBatch } from '@ethereumjs/util' /** * @hidden @@ -43,12 +36,9 @@ export type CacheMap = { [key: string]: Cache } export class DBManager { private _cache: CacheMap private _common: Common - private _db: AbstractLevel + private _db: DB - constructor( - db: AbstractLevel, - common: Common - ) { + constructor(db: DB, common: Common) { this._db = db this._common = common this._cache = { @@ -64,27 +54,29 @@ export class DBManager { * Fetches iterator heads from the db. */ async getHeads(): Promise<{ [key: string]: Uint8Array }> { - const heads = await this.get(DBTarget.Heads) + const heads = (await this.get(DBTarget.Heads)) as DBObject + if (heads === undefined) return heads + const decodedHeads: { [key: string]: Uint8Array } = {} for (const key of Object.keys(heads)) { // Heads are stored in DB as hex strings since Level converts Uint8Arrays // to nested JSON objects when they are included in a value being stored // in the DB - heads[key] = hexToBytes(heads[key]) + decodedHeads[key] = hexToBytes(heads[key] as string) } - return heads + return decodedHeads } /** * Fetches header of the head block. */ - async getHeadHeader(): Promise { + async getHeadHeader(): Promise { return this.get(DBTarget.HeadHeader) } /** * Fetches head block. */ - async getHeadBlock(): Promise { + async getHeadBlock(): Promise { return this.get(DBTarget.HeadBlock) } @@ -92,13 +84,14 @@ export class DBManager { * Fetches a block (header and body) given a block id, * which can be either its hash or its number. */ - async getBlock(blockId: Uint8Array | bigint | number): Promise { + async getBlock(blockId: Uint8Array | bigint | number): Promise { if (typeof blockId === 'number' && Number.isInteger(blockId)) { blockId = BigInt(blockId) } let number let hash + if (blockId === undefined) return undefined if (blockId instanceof Uint8Array) { hash = blockId number = await this.hashToNumber(blockId) @@ -109,30 +102,27 @@ export class DBManager { throw new Error('Unknown blockId type') } + if (hash === undefined || number === undefined) return undefined const header = await this.getHeader(hash, number) - let body: BlockBodyBytes - try { - body = await this.getBody(hash, number) - } catch (error: any) { - if (error.code !== 'LEVEL_NOT_FOUND') { - throw error - } - + const body = await this.getBody(hash, number) + if (body[0].length === 0 && body[1].length === 0) { // Do extra validations on the header since we are assuming empty transactions and uncles - if ( - !equalsBytes(header.transactionsTrie, KECCAK256_RLP) || - !equalsBytes(header.uncleHash, KECCAK256_RLP_ARRAY) - ) { - throw error + if (!equalsBytes(header.transactionsTrie, KECCAK256_RLP)) { + throw new Error('transactionsTrie root should be equal to hash of null') + } + if (!equalsBytes(header.uncleHash, KECCAK256_RLP_ARRAY)) { + throw new Error('uncle hash should be equal to hash of empty array') } - body = [[], []] // If this block had empty withdrawals push an empty array in body if (header.withdrawalsRoot !== undefined) { // Do extra validations for withdrawal before assuming empty withdrawals - if (!equalsBytes(header.withdrawalsRoot, KECCAK256_RLP)) { - throw error + if ( + !equalsBytes(header.withdrawalsRoot, KECCAK256_RLP) && + (body.length !== 3 || body[2]?.length === 0) + ) { + throw new Error('withdrawals root shoot be equal to hash of null when no withdrawals') } - body.push([]) + if (body.length !== 3) body.push([]) } } @@ -151,6 +141,9 @@ export class DBManager { */ async getBody(blockHash: Uint8Array, blockNumber: bigint): Promise { const body = await this.get(DBTarget.Body, { blockHash, blockNumber }) + if (body === undefined) { + return [[], []] + } return RLP.decode(body) as BlockBodyBytes } @@ -185,20 +178,20 @@ export class DBManager { /** * Performs a block hash to block number lookup. */ - async hashToNumber(blockHash: Uint8Array): Promise { + async hashToNumber(blockHash: Uint8Array): Promise { const value = await this.get(DBTarget.HashToNumber, { blockHash }) - return bytesToBigInt(value) + if (value === undefined) { + throw new Error(`value for ${bytesToPrefixedHexString(blockHash)} not found in DB`) + } + return value !== undefined ? bytesToBigInt(value) : undefined } /** * Performs a block number to block hash lookup. */ - async numberToHash(blockNumber: bigint): Promise { - if (blockNumber < BigInt(0)) { - throw new NotFoundError(blockNumber) - } - - return this.get(DBTarget.NumberToHash, { blockNumber }) + async numberToHash(blockNumber: bigint): Promise { + const value = await this.get(DBTarget.NumberToHash, { blockNumber }) + return value } /** @@ -211,35 +204,55 @@ export class DBManager { const cacheString = dbGetOperation.cacheString const dbKey = dbGetOperation.baseDBOp.key - const dbOpts = dbGetOperation.baseDBOp if (cacheString !== undefined) { if (this._cache[cacheString] === undefined) { throw new Error(`Invalid cache: ${cacheString}`) } let value = this._cache[cacheString].get(dbKey) - if (!value) { - value = await this._db.get(dbKey, dbOpts) - + if (value === undefined) { + value = (await this._db.get(dbKey, { + keyEncoding: dbGetOperation.baseDBOp.keyEncoding, + valueEncoding: dbGetOperation.baseDBOp.valueEncoding, + })) as Uint8Array | undefined if (value !== undefined) { - // Always cast values to Uint8Array since db sometimes returns values as `Buffer` - this._cache[cacheString].set(dbKey, Uint8Array.from(value)) + this._cache[cacheString].set(dbKey, value) } } return value } - - return this._db.get(dbKey, dbOpts) + return this._db.get(dbKey, { + keyEncoding: dbGetOperation.baseDBOp.keyEncoding, + valueEncoding: dbGetOperation.baseDBOp.valueEncoding, + }) } /** * Performs a batch operation on db. */ async batch(ops: DBOp[]) { - const convertedOps: DBOpData[] = ops.map((op) => op.baseDBOp) + const convertedOps: BatchDBOp[] = ops.map((op) => { + const type = + op.baseDBOp.type !== undefined + ? op.baseDBOp.type + : op.baseDBOp.value !== undefined + ? 'put' + : 'del' + const convertedOp = { + key: op.baseDBOp.key, + value: op.baseDBOp.value, + type, + opts: { + keyEncoding: op.baseDBOp.keyEncoding, + valueEncoding: op.baseDBOp.valueEncoding, + }, + } + if (type === 'put') return convertedOp as PutBatch + else return convertedOp as DelBatch + }) // update the current cache for each operation ops.map((op) => op.updateCache(this._cache)) - return this._db.batch(convertedOps as any) + return this._db.batch(convertedOps) } } diff --git a/packages/blockchain/src/db/operation.ts b/packages/blockchain/src/db/operation.ts index 84730ba853..fcce734c97 100644 --- a/packages/blockchain/src/db/operation.ts +++ b/packages/blockchain/src/db/operation.ts @@ -1,3 +1,5 @@ +import { KeyEncoding, ValueEncoding } from '@ethereumjs/util' + import { HEADS_KEY, HEAD_BLOCK_KEY, @@ -30,10 +32,10 @@ export enum DBTarget { * @hidden */ export interface DBOpData { - type?: string + type?: 'put' | 'del' key: Uint8Array | string - keyEncoding: string - valueEncoding?: string + keyEncoding: KeyEncoding + valueEncoding?: ValueEncoding value?: Uint8Array | object } @@ -56,22 +58,24 @@ export class DBOp { this.baseDBOp = { key: '', - keyEncoding: 'view', - valueEncoding: 'view', + keyEncoding: KeyEncoding.Bytes, + valueEncoding: ValueEncoding.Bytes, } switch (operationTarget) { case DBTarget.Heads: { this.baseDBOp.key = HEADS_KEY - this.baseDBOp.valueEncoding = 'json' + this.baseDBOp.valueEncoding = ValueEncoding.JSON break } case DBTarget.HeadHeader: { this.baseDBOp.key = HEAD_HEADER_KEY + this.baseDBOp.keyEncoding = KeyEncoding.String break } case DBTarget.HeadBlock: { this.baseDBOp.key = HEAD_BLOCK_KEY + this.baseDBOp.keyEncoding = KeyEncoding.String break } case DBTarget.HashToNumber: { @@ -117,9 +121,9 @@ export class DBOp { dbOperation.baseDBOp.type = 'put' if (operationTarget === DBTarget.Heads) { - dbOperation.baseDBOp.valueEncoding = 'json' + dbOperation.baseDBOp.valueEncoding = ValueEncoding.JSON } else { - dbOperation.baseDBOp.valueEncoding = 'view' + dbOperation.baseDBOp.valueEncoding = ValueEncoding.Bytes } return dbOperation diff --git a/packages/blockchain/src/types.ts b/packages/blockchain/src/types.ts index a1396722af..c35f5c78d8 100644 --- a/packages/blockchain/src/types.ts +++ b/packages/blockchain/src/types.ts @@ -2,7 +2,7 @@ import type { Consensus } from './consensus' import type { GenesisState } from './genesisStates' import type { Block, BlockHeader } from '@ethereumjs/block' import type { Common } from '@ethereumjs/common' -import type { AbstractLevel } from 'abstract-level' +import type { DB, DBObject } from '@ethereumjs/util' export type OnBlock = (block: Block, reorg: boolean) => Promise | void @@ -105,14 +105,9 @@ export interface BlockchainOptions { /** * Database to store blocks and metadata. - * Should be an `abstract-leveldown` compliant store - * wrapped with `encoding-down`. - * For example: - * `levelup(encode(leveldown('./db1')))` - * or use the `level` convenience package: - * `new MemoryLevel('./db1')` - */ - db?: AbstractLevel + * Can be any database implementation that adheres to the `DB` interface + */ + db?: DB /** * This flags indicates if a block should be validated along the consensus algorithm diff --git a/packages/blockchain/test/index.spec.ts b/packages/blockchain/test/index.spec.ts index 7238639bc9..7e42f73752 100644 --- a/packages/blockchain/test/index.spec.ts +++ b/packages/blockchain/test/index.spec.ts @@ -1,7 +1,7 @@ import { Block, BlockHeader } from '@ethereumjs/block' import { Chain, Common, Hardfork } from '@ethereumjs/common' +import { MapDB } from '@ethereumjs/util' import { bytesToHex, equalsBytes, hexToBytes, utf8ToBytes } from 'ethereum-cryptography/utils' -import { MemoryLevel } from 'memory-level' import * as tape from 'tape' import { Blockchain } from '../src' @@ -213,14 +213,20 @@ tape('blockchain test', (t) => { await blockchain.getBlock(5) st.fail('should throw an exception') } catch (e: any) { - st.ok(e.message.includes('NotFound'), `should throw for non-existing block-by-number request`) + st.ok( + e.message.includes('not found in DB'), + `should throw for non-existing block-by-number request` + ) } try { await blockchain.getBlock(hexToBytes('1234')) st.fail('should throw an exception') } catch (e: any) { - st.ok(e.message.includes('NotFound'), `should throw for non-existing block-by-hash request`) + st.ok( + e.message.includes('not found in DB'), + `should throw for non-existing block-by-hash request` + ) } st.end() @@ -527,6 +533,7 @@ tape('blockchain test', (t) => { await blockchain.getBlock(BigInt(1)) const block2HeaderValuesArray = blocks[2].header.raw() + block2HeaderValuesArray[1] = new Uint8Array(32) const block2Header = BlockHeader.fromValuesArray(block2HeaderValuesArray, { common: blocks[2]._common, @@ -609,7 +616,7 @@ tape('blockchain test', (t) => { }) t.test('should save headers', async (st) => { - const db = new MemoryLevel() + const db = new MapDB() const gasLimit = 8000000 const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Istanbul }) diff --git a/packages/blockchain/test/util.ts b/packages/blockchain/test/util.ts index 10d175c068..0f303811d0 100644 --- a/packages/blockchain/test/util.ts +++ b/packages/blockchain/test/util.ts @@ -1,14 +1,13 @@ import { Block, BlockHeader } from '@ethereumjs/block' import { Chain, Common, Hardfork } from '@ethereumjs/common' import { RLP } from '@ethereumjs/rlp' -import { toBytes } from '@ethereumjs/util' +import { MapDB, toBytes } from '@ethereumjs/util' import { keccak256 } from 'ethereum-cryptography/keccak' import { bytesToHex, equalsBytes, hexToBytes, utf8ToBytes } from 'ethereum-cryptography/utils' -import { MemoryLevel } from 'memory-level' import { Blockchain } from '../src' -import type { Level } from 'level' +import type { DB } from '@ethereumjs/util' export const generateBlocks = (numberOfBlocks: number, existingBlocks?: Block[]): Block[] => { const blocks = existingBlocks ? existingBlocks : [] @@ -115,37 +114,32 @@ export const isConsecutive = (blocks: Block[]) => { }) } -export const createTestDB = async (): Promise<[Level, Block]> => { +export const createTestDB = async (): Promise< + [DB, Block] +> => { const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Chainstart }) const genesis = Block.fromBlockData({ header: { number: 0 } }, { common }) - const db = new MemoryLevel() + const db = new MapDB() + await db.batch([ { type: 'put', key: hexToBytes('6800000000000000006e'), - keyEncoding: 'view', - valueEncoding: 'view', value: genesis.hash(), }, { type: 'put', key: hexToBytes('48d4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3'), - keyEncoding: 'view', - valueEncoding: 'view', value: hexToBytes('00'), }, { type: 'put', key: 'LastHeader', - keyEncoding: 'view', - valueEncoding: 'view', value: genesis.hash(), }, { type: 'put', key: 'LastBlock', - keyEncoding: 'view', - valueEncoding: 'view', value: genesis.hash(), }, { @@ -153,8 +147,6 @@ export const createTestDB = async (): Promise<[Level, Block]> => { key: hexToBytes( '680000000000000000d4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3' ), - keyEncoding: 'view', - valueEncoding: 'view', value: genesis.header.serialize(), }, { @@ -162,8 +154,6 @@ export const createTestDB = async (): Promise<[Level, Block]> => { key: hexToBytes( '680000000000000000d4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa374' ), - keyEncoding: 'view', - valueEncoding: 'view', value: RLP.encode(toBytes(17179869184)), }, { @@ -171,14 +161,11 @@ export const createTestDB = async (): Promise<[Level, Block]> => { key: hexToBytes( '620000000000000000d4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3' ), - keyEncoding: 'view', - valueEncoding: 'view', value: RLP.encode(genesis.raw().slice(1)), }, { type: 'put', key: 'heads', - valueEncoding: 'json', value: { head0: bytesToHex(Uint8Array.from([171, 205])) }, }, ]) diff --git a/packages/client/bin/cli.ts b/packages/client/bin/cli.ts index 1133c0f351..47123e3456 100755 --- a/packages/client/bin/cli.ts +++ b/packages/client/bin/cli.ts @@ -26,6 +26,7 @@ import { hideBin } from 'yargs/helpers' import { EthereumClient } from '../lib/client' import { Config, DataDirectory, SyncMode } from '../lib/config' +import { LevelDB } from '../lib/execution/level' import { getLogger } from '../lib/logging' import { Event } from '../lib/types' import { parseMultiaddrs } from '../lib/util' @@ -432,7 +433,7 @@ async function startClient(config: Config, customGenesisState?: GenesisState) { if (customGenesisState !== undefined) { const validateConsensus = config.chainCommon.consensusAlgorithm() === ConsensusAlgorithm.Clique blockchain = await Blockchain.create({ - db: dbs.chainDB, + db: new LevelDB(dbs.chainDB), genesisState: customGenesisState, common: config.chainCommon, hardforkByHeadBlockNumber: true, diff --git a/packages/client/browser/index.ts b/packages/client/browser/index.ts index 71744f2191..9527bf71c2 100644 --- a/packages/client/browser/index.ts +++ b/packages/client/browser/index.ts @@ -5,6 +5,7 @@ import { Level } from 'level' import { EthereumClient } from '../lib/client' import { Config } from '../lib/config' +import { LevelDB } from '../lib/execution/level' import { parseMultiaddrs } from '../lib/util' import { getLogger } from './logging' @@ -75,7 +76,7 @@ export async function createClient(args: any) { ) const blockchain = await Blockchain.create({ - db: chainDB, + db: new LevelDB(chainDB), common: config.chainCommon, hardforkByHeadBlockNumber: true, validateBlocks: true, diff --git a/packages/client/lib/blockchain/chain.ts b/packages/client/lib/blockchain/chain.ts index b26610fee8..f447147432 100644 --- a/packages/client/lib/blockchain/chain.ts +++ b/packages/client/lib/blockchain/chain.ts @@ -3,9 +3,11 @@ import { Blockchain } from '@ethereumjs/blockchain' import { ConsensusAlgorithm, Hardfork } from '@ethereumjs/common' import { equalsBytes } from 'ethereum-cryptography/utils' +import { LevelDB } from '../execution/level' import { Event } from '../types' import type { Config } from '../config' +import type { DB, DBObject } from '@ethereumjs/util' import type { AbstractLevel } from 'abstract-level' /** @@ -98,7 +100,7 @@ export interface ChainHeaders { */ export class Chain { public config: Config - public chainDB: AbstractLevel + public chainDB: DB public blockchain: Blockchain public opened: boolean @@ -133,7 +135,7 @@ export class Chain { options.blockchain = options.blockchain ?? new (Blockchain as any)({ - db: options.chainDB, + db: new LevelDB(options.chainDB), common: options.config.chainCommon, hardforkByHeadBlockNumber: true, validateBlocks: true, @@ -231,7 +233,7 @@ export class Chain { async close(): Promise { if (!this.opened) return false this.reset() - await this.blockchain.db.close() + await (this.blockchain.db as any)?.close?.() this.opened = false } diff --git a/packages/client/lib/config.ts b/packages/client/lib/config.ts index c184d492fb..75b72df938 100644 --- a/packages/client/lib/config.ts +++ b/packages/client/lib/config.ts @@ -569,7 +569,7 @@ export class Config { * Returns the config level db. */ static getConfigDB(networkDir: string) { - return new Level(`${networkDir}/config` as any) + return new Level(`${networkDir}/config`) } /** diff --git a/packages/client/lib/execution/level.ts b/packages/client/lib/execution/level.ts index 78f88a5ad6..35870b7468 100644 --- a/packages/client/lib/execution/level.ts +++ b/packages/client/lib/execution/level.ts @@ -1,15 +1,49 @@ +import { KeyEncoding, ValueEncoding } from '@ethereumjs/util' import { MemoryLevel } from 'memory-level' -import type { BatchDBOp, DB } from '@ethereumjs/trie' +import type { BatchDBOp, DB, DBObject, EncodingOpts } from '@ethereumjs/util' import type { AbstractLevel } from 'abstract-level' -export const ENCODING_OPTS = { keyEncoding: 'view', valueEncoding: 'view' } +// Helper to infer the `valueEncoding` option for `putting` a value in a levelDB +const getEncodings = (opts: EncodingOpts = {}) => { + const encodings = { keyEncoding: '', valueEncoding: '' } + switch (opts.valueEncoding) { + case ValueEncoding.String: + encodings.valueEncoding = 'utf8' + break + case ValueEncoding.Bytes: + encodings.valueEncoding = 'view' + break + case ValueEncoding.JSON: + encodings.valueEncoding = 'json' + break + default: + encodings.valueEncoding = 'view' + } + switch (opts.keyEncoding) { + case KeyEncoding.Bytes: + encodings.keyEncoding = 'view' + break + case KeyEncoding.Number: + case KeyEncoding.String: + encodings.keyEncoding = 'utf8' + break + default: + encodings.keyEncoding = 'utf8' + } + + return encodings +} /** * LevelDB is a thin wrapper around the underlying levelup db, - * which validates inputs and sets encoding type. + * corresponding to the {@link DB} */ -export class LevelDB implements DB { +export class LevelDB< + TKey extends Uint8Array | string = Uint8Array | string, + TValue extends Uint8Array | string | DBObject = Uint8Array | string | DBObject +> implements DB +{ _leveldb: AbstractLevel /** @@ -20,16 +54,19 @@ export class LevelDB implements DB { constructor( leveldb?: AbstractLevel ) { - this._leveldb = leveldb ?? new MemoryLevel(ENCODING_OPTS) + this._leveldb = leveldb ?? new MemoryLevel() } /** * @inheritDoc */ - async get(key: Uint8Array): Promise { - let value = null + async get(key: TKey, opts?: EncodingOpts): Promise { + let value + const encodings = getEncodings(opts) + try { - value = await this._leveldb.get(key, ENCODING_OPTS) + value = await this._leveldb.get(key, encodings) + if (value === null) return undefined } catch (error: any) { // https://github.com/Level/abstract-level/blob/915ad1317694d0ce8c580b5ab85d81e1e78a3137/abstract-level.js#L309 // This should be `true` if the error came from LevelDB @@ -38,34 +75,48 @@ export class LevelDB implements DB { throw error } } - return value as Uint8Array | null + // eslint-disable-next-line + if (value instanceof Buffer) value = Uint8Array.from(value) + return value as TValue } /** * @inheritDoc */ - async put(key: Uint8Array, val: Uint8Array): Promise { - await this._leveldb.put(key, val, ENCODING_OPTS) + async put(key: TKey, val: TValue, opts?: {}): Promise { + const encodings = getEncodings(opts) + await this._leveldb.put(key, val, encodings) } /** * @inheritDoc */ - async del(key: Uint8Array): Promise { - await this._leveldb.del(key, ENCODING_OPTS) + async del(key: TKey): Promise { + await this._leveldb.del(key) } /** * @inheritDoc */ - async batch(opStack: BatchDBOp[]): Promise { - await this._leveldb.batch(opStack, ENCODING_OPTS) + async batch(opStack: BatchDBOp[]): Promise { + const levelOps = [] + for (const op of opStack) { + const encodings = getEncodings(op.opts) + levelOps.push({ ...op, ...encodings }) + } + + // TODO: Investigate why as any is necessary + await this._leveldb.batch(levelOps as any) } /** * @inheritDoc */ - copy(): DB { - return new LevelDB(this._leveldb) + copy(): DB { + return new LevelDB(this._leveldb) + } + + open() { + return this._leveldb.open() } } diff --git a/packages/client/lib/miner/miner.ts b/packages/client/lib/miner/miner.ts index a2695b4d3c..9e510ad5d6 100644 --- a/packages/client/lib/miner/miner.ts +++ b/packages/client/lib/miner/miner.ts @@ -5,6 +5,7 @@ import { bytesToPrefixedHexString } from '@ethereumjs/util' import { bytesToHex, equalsBytes } from 'ethereum-cryptography/utils' import { MemoryLevel } from 'memory-level' +import { LevelDB } from '../execution/level' import { Event } from '../types' import type { Config } from '../config' @@ -65,7 +66,7 @@ export class Miner { ((this.config.chainCommon.consensusConfig() as CliqueConfig).period ?? this.DEFAULT_PERIOD) * 1000 // defined in ms for setTimeout use if (this.config.chainCommon.consensusType() === ConsensusType.ProofOfWork) { - this.ethash = new Ethash(new MemoryLevel()) + this.ethash = new Ethash(new LevelDB(new MemoryLevel()) as any) } } diff --git a/packages/client/lib/sync/fetcher/bytecodefetcher.ts b/packages/client/lib/sync/fetcher/bytecodefetcher.ts index cf7dc907ed..99507407ce 100644 --- a/packages/client/lib/sync/fetcher/bytecodefetcher.ts +++ b/packages/client/lib/sync/fetcher/bytecodefetcher.ts @@ -9,7 +9,7 @@ import { Fetcher } from './fetcher' import type { Peer } from '../../net/peer' import type { FetcherOptions } from './fetcher' import type { Job } from './types' -import type { BatchDBOp } from '@ethereumjs/trie' +import type { BatchDBOp } from '@ethereumjs/util' import type { Debugger } from 'debug' type ByteCodeDataResponse = Uint8Array[] & { completed?: boolean } diff --git a/packages/client/test/blockchain/chain.spec.ts b/packages/client/test/blockchain/chain.spec.ts index 287c20b5c7..e95904b4b1 100644 --- a/packages/client/test/blockchain/chain.spec.ts +++ b/packages/client/test/blockchain/chain.spec.ts @@ -2,13 +2,14 @@ // needed for karma-typescript bundling import { Block } from '@ethereumjs/block' import { Blockchain } from '@ethereumjs/blockchain' +import { KeyEncoding, ValueEncoding } from '@ethereumjs/util' import { bytesToHex, equalsBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' -import * as util from 'util' // eslint-disable-line @typescript-eslint/no-unused-vars import { Chain } from '../../lib/blockchain' import { Config } from '../../lib/config' +import type { LevelDB } from '../../lib/execution/level' import type { BlockData, HeaderData } from '@ethereumjs/block' const config = new Config({ accountCache: 10000, storageCache: 1000 }) @@ -17,13 +18,19 @@ tape('[Chain]', (t) => { t.test('should test blockchain DB is initialized', async (t) => { const chain = await Chain.create({ config }) - const db = chain.chainDB + const db = chain.chainDB as LevelDB const testKey = 'name' const testValue = 'test' + await db.put(testKey, testValue, { + keyEncoding: KeyEncoding.String, + valueEncoding: ValueEncoding.String, + }) - await db.put(testKey, testValue) - const value = await db.get(testKey) - t.equal(testValue, value, 'read value matches written value') + const value = await db.get(testKey, { + keyEncoding: KeyEncoding.String, + valueEncoding: ValueEncoding.String, + }) + t.equal(value, testValue, 'read value matches written value') t.end() }) diff --git a/packages/client/test/rpc/eth/getTransactionByBlockHashAndIndex.spec.ts b/packages/client/test/rpc/eth/getTransactionByBlockHashAndIndex.spec.ts index 1df8700f6b..b15158871f 100644 --- a/packages/client/test/rpc/eth/getTransactionByBlockHashAndIndex.spec.ts +++ b/packages/client/test/rpc/eth/getTransactionByBlockHashAndIndex.spec.ts @@ -62,7 +62,7 @@ tape(`${method}: call with unknown block hash`, async (t) => { const mockTxIndex = '0x1' const req = params(method, [mockBlockHash, mockTxIndex]) - const expectRes = checkError(t, INVALID_PARAMS, 'NotFound') + const expectRes = checkError(t, INVALID_PARAMS, 'not found in DB') await baseRequest(t, server, req, 200, expectRes) }) diff --git a/packages/client/test/sim/simutils.ts b/packages/client/test/sim/simutils.ts index 1b3fc879aa..147fc105f2 100644 --- a/packages/client/test/sim/simutils.ts +++ b/packages/client/test/sim/simutils.ts @@ -20,6 +20,7 @@ import * as net from 'node:net' import { EthereumClient } from '../../lib/client' import { Config } from '../../lib/config' +import { LevelDB } from '../../lib/execution/level' import type { Common } from '@ethereumjs/common' import type { TxOptions } from '@ethereumjs/tx' @@ -430,7 +431,7 @@ export async function createInlineClient(config: any, common: any, customGenesis ) const blockchain = await Blockchain.create({ - db: chainDB, + db: new LevelDB(chainDB), genesisState: customGenesisState, common: config.chainCommon, hardforkByHeadBlockNumber: true, diff --git a/packages/client/test/sim/snapsync.spec.ts b/packages/client/test/sim/snapsync.spec.ts index 5be6083f8e..22b012e418 100644 --- a/packages/client/test/sim/snapsync.spec.ts +++ b/packages/client/test/sim/snapsync.spec.ts @@ -139,7 +139,7 @@ tape('simple mainnet test run', async (t) => { try { if (ejsClient !== null && snapCompleted !== undefined) { // call sync if not has been called yet - void ejsClient.services[0].synchronizer.sync() + void ejsClient.services[0].synchronizer?.sync() // wait on the sync promise to complete if it has been called independently const snapSyncTimeout = new Promise((_resolve, reject) => setTimeout(reject, 40000)) try { diff --git a/packages/ethash/package.json b/packages/ethash/package.json index 2756032064..1736ef714d 100644 --- a/packages/ethash/package.json +++ b/packages/ethash/package.json @@ -40,13 +40,11 @@ "@ethereumjs/block": "^4.2.1", "@ethereumjs/rlp": "^4.0.1", "@ethereumjs/util": "^8.0.5", - "abstract-level": "^1.0.3", "bigint-crypto-utils": "^3.0.23", "ethereum-cryptography": "^1.1.2" }, "devDependencies": { - "@ethereumjs/common": "^3.1.1", - "memory-level": "^1.0.0" + "@ethereumjs/common": "^3.1.1" }, "engines": { "node": ">=16" diff --git a/packages/ethash/src/index.ts b/packages/ethash/src/index.ts index 217f374579..a53d981aea 100644 --- a/packages/ethash/src/index.ts +++ b/packages/ethash/src/index.ts @@ -1,7 +1,9 @@ import { Block, BlockHeader } from '@ethereumjs/block' import { RLP } from '@ethereumjs/rlp' import { + KeyEncoding, TWO_POW256, + ValueEncoding, bigIntToBytes, bytesToBigInt, bytesToHex, @@ -25,7 +27,7 @@ import { } from './util' import type { BlockData, HeaderData } from '@ethereumjs/block' -import type { AbstractLevel } from 'abstract-level' +import type { DB, DBObject } from '@ethereumjs/util' function xor(a: Uint8Array, b: Uint8Array) { const len = Math.max(a.length, b.length) @@ -154,27 +156,16 @@ export class Miner { } } -export type EthashCacheDB = AbstractLevel< - string | Uint8Array, - string | Uint8Array, - { - cache: string[] - fullSize: number - cacheSize: number - seed: string - } -> - export class Ethash { dbOpts: Object - cacheDB?: EthashCacheDB + cacheDB?: DB cache: Uint8Array[] epoc?: number fullSize?: number cacheSize?: number seed?: Uint8Array - constructor(cacheDB?: EthashCacheDB) { + constructor(cacheDB?: DB) { this.dbOpts = { valueEncoding: 'json', } @@ -302,21 +293,18 @@ export class Ethash { if (epoc === 0) { return [zeros(32), 0] } - let data - try { - const dbData = await this.cacheDB!.get(epoc, this.dbOpts) - data = { - cache: dbData.cache.map((el) => hexToBytes(el)), + + const dbData = await this.cacheDB!.get(epoc, { + keyEncoding: KeyEncoding.Number, + valueEncoding: ValueEncoding.JSON, + }) + if (dbData !== undefined) { + const data = { + cache: (dbData.cache as string[]).map((el: string) => hexToBytes(el)), fullSize: dbData.fullSize, cacheSize: dbData.cacheSize, - seed: hexToBytes(dbData.seed), - } - } catch (error: any) { - if (error.code !== 'LEVEL_NOT_FOUND') { - throw error + seed: hexToBytes(dbData.seed as string), } - } - if (data) { return [data.seed, epoc] } else { return findLastSeed(epoc - 1) @@ -324,20 +312,18 @@ export class Ethash { } let data - try { - const dbData = await this.cacheDB!.get(epoc, this.dbOpts) + const dbData = await this.cacheDB!.get(epoc, { + keyEncoding: KeyEncoding.Number, + valueEncoding: ValueEncoding.JSON, + }) + if (dbData !== undefined) { data = { - cache: dbData.cache.map((el) => hexToBytes(el)), + cache: (dbData.cache as string[]).map((el: string) => hexToBytes(el)), fullSize: dbData.fullSize, cacheSize: dbData.cacheSize, - seed: hexToBytes(dbData.seed), - } - } catch (error: any) { - if (error.code !== 'LEVEL_NOT_FOUND') { - throw error + seed: hexToBytes(dbData.seed as string), } } - if (!data) { this.cacheSize = await getCacheSize(epoc) this.fullSize = await getFullSize(epoc) @@ -354,14 +340,17 @@ export class Ethash { seed: bytesToHex(this.seed), cache: cache.map((el) => bytesToHex(el)), }, - this.dbOpts + { + keyEncoding: KeyEncoding.Number, + valueEncoding: ValueEncoding.JSON, + } ) } else { this.cache = data.cache.map((a: Uint8Array) => { return Uint8Array.from(a) }) - this.cacheSize = data.cacheSize - this.fullSize = data.fullSize + this.cacheSize = data.cacheSize as number + this.fullSize = data.fullSize as number this.seed = Uint8Array.from(data.seed) } } diff --git a/packages/ethash/test/block.spec.ts b/packages/ethash/test/block.spec.ts index 11aa520e7a..12aa5b567c 100644 --- a/packages/ethash/test/block.spec.ts +++ b/packages/ethash/test/block.spec.ts @@ -1,16 +1,15 @@ import { Block } from '@ethereumjs/block' import { Chain, Common, Hardfork } from '@ethereumjs/common' import { RLP } from '@ethereumjs/rlp' -import { toBytes } from '@ethereumjs/util' +import { MapDB, toBytes } from '@ethereumjs/util' import { hexToBytes } from 'ethereum-cryptography/utils' -import { MemoryLevel } from 'memory-level' import * as tape from 'tape' import { Ethash } from '../src' import type { BlockBytes } from '@ethereumjs/block' -const cacheDB = new MemoryLevel() +const cacheDB = new MapDB() const { validBlockRlp, invalidBlockRlp } = require('./ethash_block_rlp_tests.json') diff --git a/packages/ethash/test/miner.spec.ts b/packages/ethash/test/miner.spec.ts index 2d01dd51c3..c85128d872 100644 --- a/packages/ethash/test/miner.spec.ts +++ b/packages/ethash/test/miner.spec.ts @@ -1,16 +1,18 @@ import { Block } from '@ethereumjs/block' import { Chain, Common, Hardfork } from '@ethereumjs/common' -import { MemoryLevel } from 'memory-level' +import { MapDB } from '@ethereumjs/util' import * as tape from 'tape' import { Ethash } from '../src' import type { BlockHeader } from '@ethereumjs/block' -const cacheDb = new MemoryLevel() +import type { DBObject } from '@ethereumjs/util' + +const cacheDb = new MapDB() const common = new Common({ chain: Chain.Ropsten, hardfork: Hardfork.Petersburg }) tape('Check if miner works as expected', async function (t) { - const e = new Ethash(cacheDb as any) + const e = new Ethash(cacheDb) const block = Block.fromBlockData( { diff --git a/packages/trie/benchmarks/index.ts b/packages/trie/benchmarks/index.ts index 7c94b11361..a32436d8f6 100644 --- a/packages/trie/benchmarks/index.ts +++ b/packages/trie/benchmarks/index.ts @@ -1,6 +1,6 @@ import { createSuite } from './suite' import { LevelDB } from './engines/level' -import { MapDB } from '../dist' +import { MapDB } from '@ethereumjs/util' createSuite(new MapDB()) createSuite(new LevelDB()) diff --git a/packages/trie/recipes/level-legacy.ts b/packages/trie/recipes/level-legacy.ts index ff37097c8b..dc880953c5 100644 --- a/packages/trie/recipes/level-legacy.ts +++ b/packages/trie/recipes/level-legacy.ts @@ -1,6 +1,6 @@ import level from 'level-mem' -import type { BatchDBOp, DB } from '@ethereumjs/trie' +import type { BatchDBOp, DB } from '@ethereumjs/util' import type { LevelUp } from 'levelup' const ENCODING_OPTS = { keyEncoding: 'view', valueEncoding: 'view' } @@ -12,8 +12,8 @@ export class LevelDB implements DB { this._leveldb = leveldb ?? level() } - async get(key: Uint8Array): Promise { - let value: Uint8Array | null = null + async get(key: Uint8Array): Promise { + let value try { value = await this._leveldb.get(key, ENCODING_OPTS) } catch (error: any) { @@ -42,4 +42,8 @@ export class LevelDB implements DB { copy(): DB { return new LevelDB(this._leveldb) } + + open() { + return Promise.resolve() + } } diff --git a/packages/trie/recipes/level.ts b/packages/trie/recipes/level.ts index 6d6814d70d..00ba87ef08 100644 --- a/packages/trie/recipes/level.ts +++ b/packages/trie/recipes/level.ts @@ -1,6 +1,6 @@ import { MemoryLevel } from 'memory-level' -import type { BatchDBOp, DB } from '@ethereumjs/trie' +import type { BatchDBOp, DB } from '@ethereumjs/util' import type { AbstractLevel } from 'abstract-level' const ENCODING_OPTS = { keyEncoding: 'view', valueEncoding: 'view' } @@ -22,8 +22,8 @@ export class LevelDB implements DB { this._leveldb = leveldb ?? new MemoryLevel(ENCODING_OPTS) } - async get(key: Uint8Array): Promise { - let value: Uint8Array | null = null + async get(key: Uint8Array): Promise { + let value try { value = await this._leveldb.get(key, ENCODING_OPTS) } catch (error: any) { diff --git a/packages/trie/recipes/lmdb.ts b/packages/trie/recipes/lmdb.ts index 07d2ba4290..d4f3e04f8f 100644 --- a/packages/trie/recipes/lmdb.ts +++ b/packages/trie/recipes/lmdb.ts @@ -1,6 +1,6 @@ import { Database, open } from 'lmdb' -import type { BatchDBOp, DB } from '@ethereumjs/trie' +import type { BatchDBOp, DB } from '@ethereumjs/util' export class LMDB implements DB { readonly _path: string @@ -15,7 +15,7 @@ export class LMDB implements DB { }) } - async get(key: Uint8Array): Promise { + async get(key: Uint8Array): Promise { return this._database.get(key) } @@ -42,4 +42,8 @@ export class LMDB implements DB { copy(): DB { return new LMDB(this._path) } + + open() { + return Promise.resolve() + } } diff --git a/packages/trie/src/db/checkpoint.ts b/packages/trie/src/db/checkpoint.ts index 982b8f7b91..59157d55d7 100644 --- a/packages/trie/src/db/checkpoint.ts +++ b/packages/trie/src/db/checkpoint.ts @@ -1,6 +1,8 @@ -import { bytesToHex, hexStringToBytes } from '@ethereumjs/util' +import { KeyEncoding, ValueEncoding, bytesToHex, hexStringToBytes } from '@ethereumjs/util' +import { hexToBytes } from 'ethereum-cryptography/utils' -import type { BatchDBOp, Checkpoint, CheckpointDBOpts, DB } from '../types' +import type { Checkpoint, CheckpointDBOpts } from '../types' +import type { BatchDBOp, DB, DelBatch, PutBatch } from '@ethereumjs/util' import type LRUCache from 'lru-cache' const LRU = require('lru-cache') @@ -11,10 +13,10 @@ const LRU = require('lru-cache') */ export class CheckpointDB implements DB { public checkpoints: Checkpoint[] - public db: DB + public db: DB public readonly cacheSize: number - protected _cache?: LRUCache + protected _cache?: LRUCache _stats = { cache: { @@ -85,7 +87,7 @@ export class CheckpointDB implements DB { // This was the final checkpoint, we should now commit and flush everything to disk const batchOp: BatchDBOp[] = [] for (const [key, value] of keyValueMap.entries()) { - if (value === null) { + if (value === undefined) { batchOp.push({ type: 'del', key: hexStringToBytes(key), @@ -119,7 +121,7 @@ export class CheckpointDB implements DB { /** * @inheritDoc */ - async get(key: Uint8Array): Promise { + async get(key: Uint8Array): Promise { const keyHex = bytesToHex(key) if (this._cache !== undefined) { const value = this._cache.get(keyHex) @@ -132,22 +134,25 @@ export class CheckpointDB implements DB { // Lookup the value in our diff cache. We return the latest checkpointed value (which should be the value on disk) for (let index = this.checkpoints.length - 1; index >= 0; index--) { - const value = this.checkpoints[index].keyValueMap.get(bytesToHex(key)) - if (value !== undefined) { - return value + if (this.checkpoints[index].keyValueMap.has(keyHex)) { + return this.checkpoints[index].keyValueMap.get(keyHex) } } // Nothing has been found in diff cache, look up from disk - const value = await this.db.get(key) + const valueHex = await this.db.get(keyHex, { + keyEncoding: KeyEncoding.String, + valueEncoding: ValueEncoding.String, + }) this._stats.db.reads += 1 - if (value !== null) { + if (valueHex !== undefined) { this._stats.db.hits += 1 } + const value = valueHex !== undefined ? hexToBytes(valueHex) : undefined this._cache?.set(keyHex, value) if (this.hasCheckpoints()) { // Since we are a checkpoint, put this value in diff cache, // so future `get` calls will not look the key up again from disk. - this.checkpoints[this.checkpoints.length - 1].keyValueMap.set(bytesToHex(key), value) + this.checkpoints[this.checkpoints.length - 1].keyValueMap.set(keyHex, value) } return value @@ -158,11 +163,15 @@ export class CheckpointDB implements DB { */ async put(key: Uint8Array, value: Uint8Array): Promise { const keyHex = bytesToHex(key) + const valueHex = bytesToHex(value) if (this.hasCheckpoints()) { // put value in diff cache this.checkpoints[this.checkpoints.length - 1].keyValueMap.set(keyHex, value) } else { - await this.db.put(key, value) + await this.db.put(keyHex, valueHex, { + keyEncoding: KeyEncoding.String, + valueEncoding: ValueEncoding.String, + }) this._stats.db.writes += 1 if (this._cache !== undefined) { @@ -179,14 +188,16 @@ export class CheckpointDB implements DB { const keyHex = bytesToHex(key) if (this.hasCheckpoints()) { // delete the value in the current diff cache - this.checkpoints[this.checkpoints.length - 1].keyValueMap.set(keyHex, null) + this.checkpoints[this.checkpoints.length - 1].keyValueMap.set(keyHex, undefined) } else { // delete the value on disk - await this.db.del(key) + await this.db.del(keyHex, { + keyEncoding: KeyEncoding.String, + }) this._stats.db.writes += 1 if (this._cache !== undefined) { - this._cache.set(keyHex, null) + this._cache.set(keyHex, undefined) this._stats.cache.writes += 1 } } @@ -205,12 +216,22 @@ export class CheckpointDB implements DB { } } } else { - await this.db.batch(opStack) + const convertedOps = opStack.map((op) => { + const convertedOp = { + key: bytesToHex(op.key), + value: op.type === 'put' ? bytesToHex(op.value) : undefined, + type: op.type, + opts: op.opts, + } + if (op.type === 'put') return convertedOp as PutBatch + else return convertedOp as DelBatch + }) + await this.db.batch(convertedOps) } } stats(reset = true) { - const stats = { ...this._stats, size: this._cache?.length ?? 0 } + const stats = { ...this._stats, size: this._cache?.size ?? 0 } if (reset) { this._stats = { cache: { @@ -234,4 +255,8 @@ export class CheckpointDB implements DB { copy(): CheckpointDB { return new CheckpointDB({ db: this.db, cacheSize: this.cacheSize }) } + + open() { + return Promise.resolve() + } } diff --git a/packages/trie/src/db/index.ts b/packages/trie/src/db/index.ts index 0cf4fafadb..2199ccf124 100644 --- a/packages/trie/src/db/index.ts +++ b/packages/trie/src/db/index.ts @@ -1,2 +1 @@ export * from './checkpoint' -export * from './map' diff --git a/packages/trie/src/db/map.ts b/packages/trie/src/db/map.ts deleted file mode 100644 index 1a45b2879b..0000000000 --- a/packages/trie/src/db/map.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { bytesToHex } from 'ethereum-cryptography/utils' - -import type { BatchDBOp, DB } from '../types' - -export class MapDB implements DB { - _database: Map - - constructor(database?: Map) { - this._database = database ?? new Map() - } - - async get(key: Uint8Array): Promise { - const result = this._database.get(bytesToHex(key)) - - if (result !== undefined) { - return result - } - - return null - } - - async put(key: Uint8Array, val: Uint8Array): Promise { - this._database.set(bytesToHex(key), val) - } - - async del(key: Uint8Array): Promise { - this._database.delete(bytesToHex(key)) - } - - async batch(opStack: BatchDBOp[]): Promise { - for (const op of opStack) { - if (op.type === 'del') { - await this.del(op.key) - } - - if (op.type === 'put') { - await this.put(op.key, op.value) - } - } - } - - copy(): DB { - return new MapDB(this._database) - } -} diff --git a/packages/trie/src/trie/trie.ts b/packages/trie/src/trie/trie.ts index 58e5393003..c1bfcb3f7d 100644 --- a/packages/trie/src/trie/trie.ts +++ b/packages/trie/src/trie/trie.ts @@ -1,7 +1,16 @@ -import { RLP_EMPTY_STRING, bytesToHex, bytesToUtf8, equalsBytes } from '@ethereumjs/util' +import { + KeyEncoding, + MapDB, + RLP_EMPTY_STRING, + ValueEncoding, + bytesToHex, + bytesToUtf8, + equalsBytes, +} from '@ethereumjs/util' import { keccak256 } from 'ethereum-cryptography/keccak' +import { hexToBytes } from 'ethereum-cryptography/utils' -import { CheckpointDB, MapDB } from '../db' +import { CheckpointDB } from '../db' import { verifyRangeProof } from '../proof/range' import { ROOT_DB_KEY } from '../types' import { Lock } from '../util/lock' @@ -12,17 +21,15 @@ import { WalkController } from '../util/walkController' import { BranchNode, ExtensionNode, LeafNode, decodeNode, decodeRawNode, isRawNode } from './node' import type { - BatchDBOp, - DB, EmbeddedNode, FoundNodeFunction, Nibbles, Proof, - PutBatch, TrieNode, TrieOpts, TrieOptsWithDefaults, } from '../types' +import type { BatchDBOp, DB, PutBatch } from '@ethereumjs/util' interface Path { node: TrieNode | null @@ -62,7 +69,7 @@ export class Trie { this._opts = { ...this._opts, ...opts } } - this.database(opts?.db ?? new MapDB()) + this.database(opts?.db ?? new MapDB()) this.EMPTY_TRIE_ROOT = this.hash(RLP_EMPTY_STRING) this._hashLen = this.EMPTY_TRIE_ROOT.length @@ -82,16 +89,23 @@ export class Trie { if (opts?.db !== undefined && opts?.useRootPersistence === true) { if (opts?.root === undefined) { - opts.root = (await opts?.db.get(key)) ?? undefined + const rootHex = await opts?.db.get(bytesToHex(key), { + keyEncoding: KeyEncoding.String, + valueEncoding: ValueEncoding.String, + }) + opts.root = rootHex !== undefined ? hexToBytes(rootHex) : undefined } else { - await opts?.db.put(key, opts.root) + await opts?.db.put(bytesToHex(key), bytesToHex(opts.root), { + keyEncoding: KeyEncoding.String, + valueEncoding: ValueEncoding.String, + }) } } return new Trie(opts) } - database(db?: DB) { + database(db?: DB) { if (db !== undefined) { if (db instanceof CheckpointDB) { throw new Error('Cannot pass in an instance of CheckpointDB') @@ -193,6 +207,9 @@ export class Trie { return { type: 'del', key: e, + opts: { + keyEncoding: KeyEncoding.Bytes, + }, } }) } @@ -229,6 +246,9 @@ export class Trie { return { type: 'del', key: e, + opts: { + keyEncoding: KeyEncoding.Bytes, + }, } }) } diff --git a/packages/trie/src/types.ts b/packages/trie/src/types.ts index d267e847e6..ccb8148c5f 100644 --- a/packages/trie/src/types.ts +++ b/packages/trie/src/types.ts @@ -2,6 +2,7 @@ import { utf8ToBytes } from 'ethereum-cryptography/utils' import type { BranchNode, ExtensionNode, LeafNode } from './trie' import type { WalkController } from './util/walkController' +import type { DB } from '@ethereumjs/util' export type TrieNode = BranchNode | ExtensionNode | LeafNode @@ -26,7 +27,7 @@ export interface TrieOpts { /** * A database instance. */ - db?: DB + db?: DB /** * A `Uint8Array` for the root of a previously stored trie @@ -83,7 +84,7 @@ export interface CheckpointDBOpts { /** * A database instance. */ - db: DB + db: DB /** * Cache size (default: 0) @@ -91,57 +92,10 @@ export interface CheckpointDBOpts { cacheSize?: number } -export type BatchDBOp = PutBatch | DelBatch - -export interface PutBatch { - type: 'put' - key: Uint8Array - value: Uint8Array -} - -export interface DelBatch { - type: 'del' - key: Uint8Array -} - -export interface DB { - /** - * Retrieves a raw value from leveldb. - * @param key - * @returns A Promise that resolves to `Uint8Array` if a value is found or `null` if no value is found. - */ - get(key: Uint8Array): Promise - - /** - * Writes a value directly to leveldb. - * @param key The key as a `Uint8Array` - * @param value The value to be stored - */ - put(key: Uint8Array, val: Uint8Array): Promise - - /** - * Removes a raw value in the underlying leveldb. - * @param keys - */ - del(key: Uint8Array): Promise - - /** - * Performs a batch operation on db. - * @param opStack A stack of levelup operations - */ - batch(opStack: BatchDBOp[]): Promise - - /** - * Returns a copy of the DB instance, with a reference - * to the **same** underlying leveldb instance. - */ - copy(): DB -} - export type Checkpoint = { // We cannot use a Uint8Array => Uint8Array map directly. If you create two Uint8Arrays with the same internal value, // then when setting a value on the Map, it actually creates two indices. - keyValueMap: Map + keyValueMap: Map root: Uint8Array } diff --git a/packages/trie/test/db/checkpoint.spec.ts b/packages/trie/test/db/checkpoint.spec.ts index 02d4129939..6610760ff7 100644 --- a/packages/trie/test/db/checkpoint.spec.ts +++ b/packages/trie/test/db/checkpoint.spec.ts @@ -1,9 +1,9 @@ -import { hexStringToBytes, utf8ToBytes } from '@ethereumjs/util' +import { MapDB, hexStringToBytes, utf8ToBytes } from '@ethereumjs/util' import * as tape from 'tape' -import { CheckpointDB, MapDB } from '../../src' +import { CheckpointDB } from '../../src' -import type { BatchDBOp } from '../../src' +import type { BatchDBOp } from '@ethereumjs/util' tape('DB tests', (t) => { const k = utf8ToBytes('k1') @@ -17,7 +17,7 @@ tape('DB tests', (t) => { await db.put(k, v) st.deepEqual(await db.get(k), v, 'before revert: v1') await db.revert() - st.deepEqual(await db.get(k), null, 'after revert: null') + st.deepEqual(await db.get(k), undefined, 'after revert: null') st.end() }) @@ -54,7 +54,7 @@ tape('DB tests', (t) => { st.deepEqual(await db.get(k), v, 'before CP: v1') db.checkpoint(hexStringToBytes('01')) await db.del(k) - st.deepEqual(await db.get(k), null, 'before revert: null') + st.deepEqual(await db.get(k), undefined, 'before revert: undefined') await db.revert() st.deepEqual(await db.get(k), v, 'after revert: v1') st.end() diff --git a/packages/trie/test/db/db.spec.ts b/packages/trie/test/db/db.spec.ts index 0f3f1969e5..6e9880fac8 100644 --- a/packages/trie/test/db/db.spec.ts +++ b/packages/trie/test/db/db.spec.ts @@ -1,12 +1,10 @@ -import { equalsBytes, utf8ToBytes } from '@ethereumjs/util' +import { MapDB, equalsBytes, utf8ToBytes } from '@ethereumjs/util' import * as tape from 'tape' -import { MapDB } from '../../src' - -import type { BatchDBOp } from '../../src' +import type { BatchDBOp } from '@ethereumjs/util' tape('DB tests', (t) => { - const db = new MapDB() + const db = new MapDB() const k = utf8ToBytes('k1') const v = utf8ToBytes('v1') diff --git a/packages/trie/test/proof/range.spec.ts b/packages/trie/test/proof/range.spec.ts index f1c2118f63..01cdaf722b 100644 --- a/packages/trie/test/proof/range.spec.ts +++ b/packages/trie/test/proof/range.spec.ts @@ -1,4 +1,5 @@ import { + MapDB, compareBytes, concatBytes, hexStringToBytes, @@ -8,9 +9,9 @@ import { import * as crypto from 'crypto' import * as tape from 'tape' -import { MapDB, Trie } from '../../src' +import { Trie } from '../../src' -import type { DB } from '../../src' +import type { DB } from '@ethereumjs/util' // reference: https://github.com/ethereum/go-ethereum/blob/20356e57b119b4e70ce47665a71964434e15200d/trie/proof_test.go @@ -21,7 +22,7 @@ const TRIE_SIZE = 512 * @param addKey - whether to add 100 ordered keys * @returns Trie object and sorted entries */ -async function randomTrie(db: DB, addKey: boolean = true) { +async function randomTrie(db: DB, addKey: boolean = true) { const entries: [Uint8Array, Uint8Array][] = [] const trie = new Trie({ db }) diff --git a/packages/trie/test/stream.spec.ts b/packages/trie/test/stream.spec.ts index c08606befa..e7e49b8723 100644 --- a/packages/trie/test/stream.spec.ts +++ b/packages/trie/test/stream.spec.ts @@ -3,7 +3,7 @@ import * as tape from 'tape' import { Trie } from '../src' -import type { BatchDBOp } from '../src' +import type { BatchDBOp } from '@ethereumjs/util' tape('kv stream test', function (tester) { const it = tester.test diff --git a/packages/trie/test/trie/checkpoint.spec.ts b/packages/trie/test/trie/checkpoint.spec.ts index 6d666fecb8..551059b2a5 100644 --- a/packages/trie/test/trie/checkpoint.spec.ts +++ b/packages/trie/test/trie/checkpoint.spec.ts @@ -1,11 +1,11 @@ -import { bytesToHex, bytesToUtf8, equalsBytes, utf8ToBytes } from '@ethereumjs/util' +import { MapDB, bytesToHex, bytesToUtf8, equalsBytes, utf8ToBytes } from '@ethereumjs/util' import { createHash } from 'crypto' import { keccak256 } from 'ethereum-cryptography/keccak' import * as tape from 'tape' -import { MapDB, ROOT_DB_KEY, Trie } from '../../src' +import { ROOT_DB_KEY, Trie } from '../../src' -import type { BatchDBOp } from '../../src' +import type { BatchDBOp } from '@ethereumjs/util' tape('testing checkpoints', function (tester) { const it = tester.test @@ -277,7 +277,7 @@ tape('testing checkpoints', function (tester) { // I.e. the trie is pruned. t.deepEqual( // @ts-expect-error - [...CommittedState._db.db._database.values()].map((value) => bytesToHex(value)), + [...CommittedState._db.db._database.values()].map((value) => value), [ 'd7eba6ee0f011acb031b79554d57001c42fbfabb150eb9fdd3b6d434f7b791eb', 'e3a1202418cf7414b1e6c2c8d92b4673eecdb4aac88f7f58623e3be903aefb2fd4655c32', diff --git a/packages/trie/test/trie/secure.spec.ts b/packages/trie/test/trie/secure.spec.ts index 30645e3fe2..590eefb312 100644 --- a/packages/trie/test/trie/secure.spec.ts +++ b/packages/trie/test/trie/secure.spec.ts @@ -1,4 +1,5 @@ import { + MapDB, bytesToPrefixedHexString, bytesToUtf8, equalsBytes, @@ -8,7 +9,7 @@ import { import { createHash } from 'crypto' import * as tape from 'tape' -import { MapDB, ROOT_DB_KEY, Trie } from '../../src' +import { ROOT_DB_KEY, Trie } from '../../src' tape('SecureTrie', function (t) { const trie = new Trie({ useKeyHashing: true, db: new MapDB() }) @@ -89,7 +90,7 @@ tape('SecureTrie', function (t) { await trie.put(ROOT_DB_KEY, utf8ToBytes('bar')) st.fail("Attempting to set '__root__' should fail but it did not.") - } catch ({ message }) { + } catch ({ message }: any) { st.equal(message, "Attempted to set '__root__' key but it is not allowed.") } }) diff --git a/packages/trie/test/trie/trie.spec.ts b/packages/trie/test/trie/trie.spec.ts index 8ffcf94607..6657511611 100644 --- a/packages/trie/test/trie/trie.spec.ts +++ b/packages/trie/test/trie/trie.spec.ts @@ -1,8 +1,8 @@ -import { KECCAK256_RLP, bytesToHex, equalsBytes, utf8ToBytes } from '@ethereumjs/util' +import { KECCAK256_RLP, MapDB, bytesToHex, equalsBytes, utf8ToBytes } from '@ethereumjs/util' import { keccak256 } from 'ethereum-cryptography/keccak' import * as tape from 'tape' -import { ROOT_DB_KEY as BASE_DB_KEY, MapDB, Trie } from '../../src' +import { ROOT_DB_KEY as BASE_DB_KEY, Trie } from '../../src' for (const { constructor, defaults, title } of [ { @@ -98,7 +98,7 @@ for (const { constructor, defaults, title } of [ }) // @ts-expect-error - st.equal(await trie._db.get(ROOT_DB_KEY), null) + st.equal(await trie._db.get(ROOT_DB_KEY), undefined) await trie.put(utf8ToBytes('foo'), utf8ToBytes('bar')) @@ -137,12 +137,12 @@ for (const { constructor, defaults, title } of [ }) // @ts-expect-error - st.equal(await trie._db.get(ROOT_DB_KEY), null) + st.equal(await trie._db.get(ROOT_DB_KEY), undefined) await trie.put(utf8ToBytes('do_not_persist_with_db'), utf8ToBytes('bar')) // @ts-expect-error - st.equal(await trie._db.get(ROOT_DB_KEY), null) + st.equal(await trie._db.get(ROOT_DB_KEY), undefined) st.end() } @@ -152,22 +152,22 @@ for (const { constructor, defaults, title } of [ const trie = await constructor.create({ ...defaults, useRootPersistence: true }) // @ts-expect-error - st.equal(await trie._db.get(ROOT_DB_KEY), null) + st.equal(await trie._db.get(ROOT_DB_KEY), undefined) await trie.put(utf8ToBytes('do_not_persist_without_db'), utf8ToBytes('bar')) // @ts-expect-error - st.notEqual(await trie._db.get(ROOT_DB_KEY), null) + st.notEqual(await trie._db.get(ROOT_DB_KEY), undefined) st.end() }) t.test('persist and restore the root', async function (st) { - const db = new MapDB() + const db = new MapDB() const trie = await constructor.create({ ...defaults, db, useRootPersistence: true }) // @ts-expect-error - st.equal(await trie._db.get(ROOT_DB_KEY), null) + st.equal(await trie._db.get(ROOT_DB_KEY), undefined) await trie.put(utf8ToBytes('foo'), utf8ToBytes('bar')) // @ts-expect-error st.equal(bytesToHex(await trie._db.get(ROOT_DB_KEY)), EXPECTED_ROOTS) @@ -184,7 +184,7 @@ for (const { constructor, defaults, title } of [ useRootPersistence: true, }) // @ts-expect-error - st.equal(await empty._db.get(ROOT_DB_KEY), null) + st.equal(await empty._db.get(ROOT_DB_KEY), undefined) st.end() }) @@ -195,7 +195,7 @@ for (const { constructor, defaults, title } of [ try { await trie.put(BASE_DB_KEY, utf8ToBytes('bar')) st.fail("Attempting to set '__root__' should fail but it did not.") - } catch ({ message }) { + } catch ({ message }: any) { st.equal(message, "Attempted to set '__root__' key but it is not allowed.") } diff --git a/packages/util/src/db.ts b/packages/util/src/db.ts new file mode 100644 index 0000000000..fd79f07775 --- /dev/null +++ b/packages/util/src/db.ts @@ -0,0 +1,82 @@ +export type DBObject = { + [key: string]: string | string[] | number +} +export type BatchDBOp< + TKey extends Uint8Array | string | number = Uint8Array, + TValue extends Uint8Array | string | DBObject = Uint8Array +> = PutBatch | DelBatch + +export enum KeyEncoding { + String = 'string', + Bytes = 'view', + Number = 'number', +} + +export enum ValueEncoding { + String = 'string', + Bytes = 'view', + JSON = 'json', +} + +export type EncodingOpts = { + keyEncoding?: KeyEncoding + valueEncoding?: ValueEncoding +} +export interface PutBatch< + TKey extends Uint8Array | string | number = Uint8Array, + TValue extends Uint8Array | string | DBObject = Uint8Array +> { + type: 'put' + key: TKey + value: TValue + opts?: EncodingOpts +} + +export interface DelBatch { + type: 'del' + key: TKey + opts?: EncodingOpts +} + +export interface DB< + TKey extends Uint8Array | string | number = Uint8Array, + TValue extends Uint8Array | string | DBObject = Uint8Array +> { + /** + * Retrieves a raw value from db. + * @param key + * @returns A Promise that resolves to `Uint8Array` if a value is found or `undefined` if no value is found. + */ + get(key: TKey, opts?: EncodingOpts): Promise + + /** + * Writes a value directly to db. + * @param key The key as a `TValue` + * @param value The value to be stored + */ + put(key: TKey, val: TValue, opts?: EncodingOpts): Promise + + /** + * Removes a raw value in the underlying db. + * @param keys + */ + del(key: TKey, opts?: EncodingOpts): Promise + + /** + * Performs a batch operation on db. + * @param opStack A stack of levelup operations + */ + batch(opStack: BatchDBOp[]): Promise + + /** + * Returns a copy of the DB instance, with a reference + * to the **same** underlying db instance. + */ + copy(): DB + + /** + * Opens the database -- if applicable + */ + open(): Promise + // TODO - decide if we actually need open/close - it's not required for maps and Level automatically opens the DB when you instantiate it +} diff --git a/packages/util/src/index.ts b/packages/util/src/index.ts index b3cbbf3656..7ba80184ca 100644 --- a/packages/util/src/index.ts +++ b/packages/util/src/index.ts @@ -18,6 +18,11 @@ export * from './account' */ export * from './address' +/** + * DB type + */ +export * from './db' + /** * Withdrawal type */ @@ -67,4 +72,5 @@ export { } from './internal' export * from './kzg' export * from './lock' +export * from './mapDB' export * from './provider' diff --git a/packages/util/src/mapDB.ts b/packages/util/src/mapDB.ts new file mode 100644 index 0000000000..efb17da7f8 --- /dev/null +++ b/packages/util/src/mapDB.ts @@ -0,0 +1,50 @@ +import { bytesToHex } from 'ethereum-cryptography/utils' + +import type { BatchDBOp, DB, DBObject } from './db' + +export class MapDB< + TKey extends Uint8Array | string | number, + TValue extends Uint8Array | string | DBObject +> implements DB +{ + _database: Map + + constructor(database?: Map) { + this._database = database ?? new Map() + } + + async get(key: TKey): Promise { + const dbKey = key instanceof Uint8Array ? bytesToHex(key) : key.toString() + return this._database.get(dbKey as TKey) + } + + async put(key: TKey, val: TValue): Promise { + const dbKey = key instanceof Uint8Array ? bytesToHex(key) : key.toString() + this._database.set(dbKey as TKey, val) + } + + async del(key: TKey): Promise { + const dbKey = key instanceof Uint8Array ? bytesToHex(key) : key.toString() + this._database.delete(dbKey as TKey) + } + + async batch(opStack: BatchDBOp[]): Promise { + for (const op of opStack) { + if (op.type === 'del') { + await this.del(op.key) + } + + if (op.type === 'put') { + await this.put(op.key, op.value) + } + } + } + + copy(): DB { + return new MapDB(this._database) + } + + open() { + return Promise.resolve() + } +} diff --git a/packages/vm/package.json b/packages/vm/package.json index c03a914755..1c1eb18e8d 100644 --- a/packages/vm/package.json +++ b/packages/vm/package.json @@ -78,8 +78,6 @@ "@types/node-dir": "^0.0.34", "benchmark": "^2.1.4", "c-kzg": "^2.0.4", - "level": "^8.0.0", - "memory-level": "^1.0.0", "minimist": "^1.2.5", "node-dir": "^0.1.17", "nyc": "^15.1.0", diff --git a/packages/vm/test/api/runBlock.spec.ts b/packages/vm/test/api/runBlock.spec.ts index 1025e19789..12423467e2 100644 --- a/packages/vm/test/api/runBlock.spec.ts +++ b/packages/vm/test/api/runBlock.spec.ts @@ -237,7 +237,10 @@ tape('runBlock() -> API parameter usage/data errors', async (t) => { .runBlock({ block }) .then(() => t.fail('should have returned error')) .catch((e) => { - t.ok(e.code.includes('LEVEL_NOT_FOUND'), 'block failed validation due to no parent header') + t.ok( + e.message.includes('not found in DB'), + 'block failed validation due to no parent header' + ) }) }) diff --git a/packages/vm/test/api/utils.ts b/packages/vm/test/api/utils.ts index 8cd52c9e92..d26e8f3c95 100644 --- a/packages/vm/test/api/utils.ts +++ b/packages/vm/test/api/utils.ts @@ -6,6 +6,7 @@ import { hexToBytes } from 'ethereum-cryptography/utils' import { MemoryLevel } from 'memory-level' import { VM } from '../../src/vm' +import { LevelDB } from '../level' import type { VMOpts } from '../../src/types' import type { Block } from '@ethereumjs/block' @@ -24,7 +25,7 @@ export async function setBalance(vm: VM, address: Address, balance = BigInt(1000 } export async function setupVM(opts: VMOpts & { genesisBlock?: Block } = {}) { - const db: any = new MemoryLevel() + const db: any = new LevelDB(new MemoryLevel()) const { common, genesisBlock } = opts if (opts.blockchain === undefined) { opts.blockchain = await Blockchain.create({ diff --git a/packages/vm/test/level.ts b/packages/vm/test/level.ts new file mode 100644 index 0000000000..4c2b6d318c --- /dev/null +++ b/packages/vm/test/level.ts @@ -0,0 +1,78 @@ +import { MemoryLevel } from 'memory-level' + +import type { BatchDBOp, DB } from '@ethereumjs/util' +import type { AbstractLevel } from 'abstract-level' + +export const ENCODING_OPTS = { keyEncoding: 'view', valueEncoding: 'view' } + +/** + * LevelDB is a thin wrapper around the underlying levelup db, + * which validates inputs and sets encoding type. + */ +export class LevelDB implements DB { + _leveldb: AbstractLevel + + /** + * Initialize a DB instance. If `leveldb` is not provided, DB + * defaults to an [in-memory store](https://github.com/Level/memdown). + * @param leveldb - An abstract-leveldown compliant store + */ + constructor( + leveldb?: AbstractLevel + ) { + this._leveldb = leveldb ?? new MemoryLevel(ENCODING_OPTS) + } + + /** + * @inheritDoc + */ + // @ts-expect-error + async get(key: Uint8Array): Promise { + let value + try { + value = await this._leveldb.get(key, ENCODING_OPTS) + if (value === null) return undefined + } catch (error: any) { + // https://github.com/Level/abstract-level/blob/915ad1317694d0ce8c580b5ab85d81e1e78a3137/abstract-level.js#L309 + // This should be `true` if the error came from LevelDB + // so we can check for `NOT true` to identify any non-404 errors + if (error.notFound !== true) { + throw error + } + } + return value + } + + /** + * @inheritDoc + */ + async put(key: Uint8Array, val: Uint8Array): Promise { + await this._leveldb.put(key, val, ENCODING_OPTS) + } + + /** + * @inheritDoc + */ + async del(key: Uint8Array): Promise { + await this._leveldb.del(key, ENCODING_OPTS) + } + + /** + * @inheritDoc + */ + async batch(opStack: BatchDBOp[]): Promise { + await this._leveldb.batch(opStack, ENCODING_OPTS) + } + + /** + * @inheritDoc + */ + copy(): DB { + //@ts-expect-error + return new LevelDB(this._leveldb) + } + + open() { + return this._leveldb.open() + } +} diff --git a/packages/vm/test/tester/runners/BlockchainTestsRunner.ts b/packages/vm/test/tester/runners/BlockchainTestsRunner.ts index 2ff3dfbe5b..bd0eb40452 100644 --- a/packages/vm/test/tester/runners/BlockchainTestsRunner.ts +++ b/packages/vm/test/tester/runners/BlockchainTestsRunner.ts @@ -5,10 +5,8 @@ import { RLP } from '@ethereumjs/rlp' import { DefaultStateManager } from '@ethereumjs/statemanager' import { Trie } from '@ethereumjs/trie' import { TransactionFactory } from '@ethereumjs/tx' -import { bytesToBigInt, isHexPrefixed, stripHexPrefix, toBytes } from '@ethereumjs/util' +import { MapDB, bytesToBigInt, isHexPrefixed, stripHexPrefix, toBytes } from '@ethereumjs/util' import { bytesToHex, hexToBytes } from 'ethereum-cryptography/utils' -import { Level } from 'level' -import { MemoryLevel } from 'memory-level' import { setupPreConditions, verifyPostConditions } from '../../util' @@ -37,7 +35,7 @@ export async function runBlockchainTest(options: any, testData: any, t: tape.Tes let common = options.common.copy() as Common common.setHardforkByBlockNumber(0) - let cacheDB = new Level('./.cachedb') + let cacheDB = new MapDB() let state = new Trie({ useKeyHashing: true }) let stateManager = new DefaultStateManager({ trie: state, @@ -66,7 +64,6 @@ export async function runBlockchainTest(options: any, testData: any, t: tape.Tes } let blockchain = await Blockchain.create({ - db: new MemoryLevel(), common, validateBlocks: true, validateConsensus: validatePow, @@ -215,7 +212,7 @@ export async function runBlockchainTest(options: any, testData: any, t: tape.Tes throw e } - await cacheDB.close() + // await cacheDB._leveldb.close() if (expectException !== false) { t.fail(`expected exception but test did not throw an exception: ${expectException}`) @@ -236,7 +233,7 @@ export async function runBlockchainTest(options: any, testData: any, t: tape.Tes const end = Date.now() const timeSpent = `${(end - begin) / 1000} secs` t.comment(`Time: ${timeSpent}`) - await cacheDB.close() + // await cacheDB._leveldb.close() // @ts-ignore Explicitly delete objects for memory optimization (early GC) common = blockchain = state = stateManager = vm = cacheDB = null // eslint-disable-line From 1a8c77ef2b24997d862c59645c4d9b6374bedc0a Mon Sep 17 00:00:00 2001 From: acolytec3 Date: Fri, 14 Apr 2023 02:40:01 -0400 Subject: [PATCH 39/53] Kick `ethers` off the `block` (#2633) * Make `block.fromEthersProvider` provider agnostic * Finish block * Move provider utils to util * Remove ethers from tx * skip fetch test in browser context * Fix tests * Fix td typing * more td typing * Switch fetch dep to micro-ftch * Add error handling --- packages/client/test/client.spec.ts | 4 +- .../test/integration/beaconsync.spec.ts | 2 +- packages/client/test/miner/miner.spec.ts | 2 +- .../client/test/miner/pendingBlock.spec.ts | 2 +- .../client/test/net/peer/rlpxpeer.spec.ts | 2 +- .../test/net/server/libp2pserver.spec.ts | 2 +- .../client/test/net/server/rlpxserver.spec.ts | 4 +- .../test/rpc/engine/newPayloadV1.spec.ts | 2 +- .../test/rpc/engine/newPayloadV2.spec.ts | 2 +- .../test/rpc/engine/newPayloadV3.spec.ts | 2 +- .../test/service/fullethereumservice.spec.ts | 12 +++--- .../test/service/lightethereumservice.spec.ts | 8 ++-- packages/client/test/sync/beaconsync.spec.ts | 2 +- .../test/sync/fetcher/headerfetcher.spec.ts | 2 +- packages/client/test/sync/fullsync.spec.ts | 2 +- packages/client/test/sync/lightsync.spec.ts | 2 +- packages/client/test/sync/skeleton.spec.ts | 2 +- packages/client/test/sync/snapsync.spec.ts | 2 +- .../statemanager/src/ethersStateManager.ts | 43 ++++++++++++++++++- .../test/ethersStateManager.spec.ts | 11 +++-- 20 files changed, 76 insertions(+), 34 deletions(-) diff --git a/packages/client/test/client.spec.ts b/packages/client/test/client.spec.ts index 94b6d9b68f..c669d6a846 100644 --- a/packages/client/test/client.spec.ts +++ b/packages/client/test/client.spec.ts @@ -16,7 +16,7 @@ tape('[EthereumClient]', async (t) => { FullEthereumService.prototype.open = td.func() FullEthereumService.prototype.start = td.func() FullEthereumService.prototype.stop = td.func() - td.replace('../lib/service', { FullEthereumService }) + td.replace('../lib/service', { FullEthereumService }) td.when(FullEthereumService.prototype.open()).thenResolve() td.when(FullEthereumService.prototype.start()).thenResolve() td.when(FullEthereumService.prototype.stop()).thenResolve() @@ -31,7 +31,7 @@ tape('[EthereumClient]', async (t) => { Server.prototype.start = td.func() Server.prototype.stop = td.func() Server.prototype.bootstrap = td.func() - td.replace('../lib/net/server/server', { Server }) + td.replace('../lib/net/server/server', { Server }) td.when(Server.prototype.start()).thenResolve() td.when(Server.prototype.stop()).thenResolve() td.when(Server.prototype.bootstrap()).thenResolve() diff --git a/packages/client/test/integration/beaconsync.spec.ts b/packages/client/test/integration/beaconsync.spec.ts index 62d46f0d3d..eaa2a364e3 100644 --- a/packages/client/test/integration/beaconsync.spec.ts +++ b/packages/client/test/integration/beaconsync.spec.ts @@ -16,7 +16,7 @@ tape('[Integration:BeaconSync]', async (t) => { t.test('should sync blocks', async (t) => { BlockHeader.prototype._consensusFormatValidation = td.func() - td.replace('@ethereumjs/block', { BlockHeader }) + td.replace('@ethereumjs/block', { BlockHeader }) const [remoteServer, remoteService] = await setup({ location: '127.0.0.2', height: 20, common }) const [localServer, localService] = await setup({ location: '127.0.0.1', height: 0, common }) diff --git a/packages/client/test/miner/miner.spec.ts b/packages/client/test/miner/miner.spec.ts index 6cfab9709d..37969eba1f 100644 --- a/packages/client/test/miner/miner.spec.ts +++ b/packages/client/test/miner/miner.spec.ts @@ -38,7 +38,7 @@ const setBalance = async (vm: VM, address: Address, balance: bigint) => { tape('[Miner]', async (t) => { const originalValidate = BlockHeader.prototype._consensusFormatValidation BlockHeader.prototype._consensusFormatValidation = td.func() - td.replace('@ethereumjs/block', { BlockHeader }) + td.replace('@ethereumjs/block', { BlockHeader }) // Stub out setStateRoot so txPool.validate checks will pass since correct state root // doesn't exist in fakeChain state anyway diff --git a/packages/client/test/miner/pendingBlock.spec.ts b/packages/client/test/miner/pendingBlock.spec.ts index 54a556e3e1..d6bc33ec6a 100644 --- a/packages/client/test/miner/pendingBlock.spec.ts +++ b/packages/client/test/miner/pendingBlock.spec.ts @@ -81,7 +81,7 @@ const setup = () => { tape('[PendingBlock]', async (t) => { const originalValidate = BlockHeader.prototype._consensusFormatValidation BlockHeader.prototype._consensusFormatValidation = td.func() - td.replace('@ethereumjs/block', { BlockHeader }) + td.replace('@ethereumjs/block', { BlockHeader }) const originalSetStateRoot = DefaultStateManager.prototype.setStateRoot DefaultStateManager.prototype.setStateRoot = td.func() diff --git a/packages/client/test/net/peer/rlpxpeer.spec.ts b/packages/client/test/net/peer/rlpxpeer.spec.ts index f2ea71f7a5..d2efaa6e32 100644 --- a/packages/client/test/net/peer/rlpxpeer.spec.ts +++ b/packages/client/test/net/peer/rlpxpeer.spec.ts @@ -12,7 +12,7 @@ tape('[RlpxPeer]', async (t) => { connect(_: any) {} } RLPx.prototype.connect = td.func() - td.replace('@ethereumjs/devp2p', { DPT, ETH, LES, SNAP, RLPx }) + td.replace('@ethereumjs/devp2p', { DPT, ETH, LES, SNAP, RLPx }) const { RlpxPeer } = await import('../../../lib/net/peer/rlpxpeer') t.test('should initialize correctly', async (t) => { diff --git a/packages/client/test/net/server/libp2pserver.spec.ts b/packages/client/test/net/server/libp2pserver.spec.ts index 71c988d445..24c0442996 100644 --- a/packages/client/test/net/server/libp2pserver.spec.ts +++ b/packages/client/test/net/server/libp2pserver.spec.ts @@ -24,7 +24,7 @@ tape('[Libp2pServer]', async (t) => { Libp2pNode.prototype.handle = td.func() Libp2pNode.prototype.start = td.func() Libp2pNode.prototype.stop = td.func() - td.replace('../../../lib/net/peer/libp2pnode', { Libp2pNode }) + td.replace('../../../lib/net/peer/libp2pnode', { Libp2pNode }) const conn0 = 'conn0' as any const conn1 = 'conn1' as any diff --git a/packages/client/test/net/server/rlpxserver.spec.ts b/packages/client/test/net/server/rlpxserver.spec.ts index 9f346ac631..6d05c16241 100644 --- a/packages/client/test/net/server/rlpxserver.spec.ts +++ b/packages/client/test/net/server/rlpxserver.spec.ts @@ -23,7 +23,7 @@ tape('[RlpxServer]', async (t) => { } RlpxPeer.prototype.accept = td.func() RlpxPeer.capabilities = td.func() - td.replace('../../../lib/net/peer/rlpxpeer', { RlpxPeer }) + td.replace('../../../lib/net/peer/rlpxpeer', { RlpxPeer }) class RLPx extends EventEmitter { listen(_: any, _2: any) {} @@ -36,7 +36,7 @@ tape('[RlpxServer]', async (t) => { DPT.prototype.bind = td.func() DPT.prototype.getDnsPeers = td.func() - td.replace('@ethereumjs/devp2p', { DPT, RLPx }) + td.replace('@ethereumjs/devp2p', { DPT, RLPx }) const { RlpxServer } = await import('../../../lib/net/server/rlpxserver') diff --git a/packages/client/test/rpc/engine/newPayloadV1.spec.ts b/packages/client/test/rpc/engine/newPayloadV1.spec.ts index 0f98f83415..fdc5602d9e 100644 --- a/packages/client/test/rpc/engine/newPayloadV1.spec.ts +++ b/packages/client/test/rpc/engine/newPayloadV1.spec.ts @@ -143,7 +143,7 @@ tape(`${method}: invalid terminal block`, async (t) => { } BlockHeader.prototype._consensusFormatValidation = td.func() - td.replace('@ethereumjs/block', { BlockHeader }) + td.replace('@ethereumjs/block', { BlockHeader }) const { server } = await setupChain(genesisWithHigherTtd, 'post-merge', { engine: true, diff --git a/packages/client/test/rpc/engine/newPayloadV2.spec.ts b/packages/client/test/rpc/engine/newPayloadV2.spec.ts index 425d485af6..a87f45a6a4 100644 --- a/packages/client/test/rpc/engine/newPayloadV2.spec.ts +++ b/packages/client/test/rpc/engine/newPayloadV2.spec.ts @@ -138,7 +138,7 @@ tape(`${method}: call with executionPayloadV1`, (v1) => { } BlockHeader.prototype._consensusFormatValidation = td.func() - td.replace('@ethereumjs/block', { BlockHeader }) + td.replace('@ethereumjs/block', { BlockHeader }) const { server } = await setupChain(genesisWithHigherTtd, 'post-merge', { engine: true, diff --git a/packages/client/test/rpc/engine/newPayloadV3.spec.ts b/packages/client/test/rpc/engine/newPayloadV3.spec.ts index efa1e8696b..6ac9363220 100644 --- a/packages/client/test/rpc/engine/newPayloadV3.spec.ts +++ b/packages/client/test/rpc/engine/newPayloadV3.spec.ts @@ -138,7 +138,7 @@ tape(`${method}: call with executionPayloadV1`, (v1) => { } BlockHeader.prototype._consensusFormatValidation = td.func() - td.replace('@ethereumjs/block', { BlockHeader }) + td.replace('@ethereumjs/block', { BlockHeader }) const { server } = await setupChain(genesisWithHigherTtd, 'post-merge', { engine: true, diff --git a/packages/client/test/service/fullethereumservice.spec.ts b/packages/client/test/service/fullethereumservice.spec.ts index 53201fe2db..90eb850522 100644 --- a/packages/client/test/service/fullethereumservice.spec.ts +++ b/packages/client/test/service/fullethereumservice.spec.ts @@ -23,14 +23,14 @@ tape('[FullEthereumService]', async (t) => { PeerPool.prototype.close = td.func() PeerPool.prototype.start = td.func() PeerPool.prototype.stop = td.func() - td.replace('../../lib/net/peerpool', { PeerPool }) + td.replace('../../lib/net/peerpool', { PeerPool }) const MockChain = td.constructor([] as any) MockChain.prototype.open = td.func() - td.replace('../../lib/blockchain', { Chain: MockChain }) + td.replace('../../lib/blockchain', { Chain: MockChain }) const EthProtocol = td.constructor([] as any) const LesProtocol = td.constructor([] as any) - td.replace('../../lib/net/protocol/ethprotocol', { EthProtocol }) - td.replace('../../lib/net/protocol/lesprotocol', { LesProtocol }) + td.replace('../../lib/net/protocol/ethprotocol', { EthProtocol }) + td.replace('../../lib/net/protocol/lesprotocol', { LesProtocol }) class FullSynchronizer { start() {} stop() {} @@ -55,14 +55,14 @@ tape('[FullEthereumService]', async (t) => { BeaconSynchronizer.prototype.stop = td.func() BeaconSynchronizer.prototype.open = td.func() BeaconSynchronizer.prototype.close = td.func() - td.replace('../../lib/sync', { FullSynchronizer, BeaconSynchronizer }) + td.replace('../../lib/sync', { FullSynchronizer, BeaconSynchronizer }) class Block { static fromValuesArray() { return {} } } - td.replace('@ethereumjs/block', { Block }) + td.replace('@ethereumjs/block', { Block }) const { FullEthereumService } = await import('../../lib/service/fullethereumservice') t.test('should initialize correctly', async (t) => { diff --git a/packages/client/test/service/lightethereumservice.spec.ts b/packages/client/test/service/lightethereumservice.spec.ts index 9b7d62d567..ac43994a23 100644 --- a/packages/client/test/service/lightethereumservice.spec.ts +++ b/packages/client/test/service/lightethereumservice.spec.ts @@ -12,12 +12,12 @@ tape('[LightEthereumService]', async (t) => { } PeerPool.prototype.open = td.func() PeerPool.prototype.close = td.func() - td.replace('../../lib/net/peerpool', { PeerPool }) + td.replace('../../lib/net/peerpool', { PeerPool }) const MockChain = td.constructor([] as any) MockChain.prototype.open = td.func() - td.replace('../../lib/blockchain', { MockChain }) + td.replace('../../lib/blockchain', { MockChain }) const LesProtocol = td.constructor([] as any) - td.replace('../../lib/net/protocol/lesprotocol', { LesProtocol }) + td.replace('../../lib/net/protocol/lesprotocol', { LesProtocol }) class LightSynchronizer { start() {} stop() {} @@ -28,7 +28,7 @@ tape('[LightEthereumService]', async (t) => { LightSynchronizer.prototype.stop = td.func() LightSynchronizer.prototype.open = td.func() LightSynchronizer.prototype.close = td.func() - td.replace('../../lib/sync/lightsync', { LightSynchronizer }) + td.replace('../../lib/sync/lightsync', { LightSynchronizer }) const { LightEthereumService } = await import('../../lib/service/lightethereumservice') diff --git a/packages/client/test/sync/beaconsync.spec.ts b/packages/client/test/sync/beaconsync.spec.ts index fd7fd9f550..50b9c6b53b 100644 --- a/packages/client/test/sync/beaconsync.spec.ts +++ b/packages/client/test/sync/beaconsync.spec.ts @@ -37,7 +37,7 @@ tape('[BeaconSynchronizer]', async (t) => { ReverseBlockFetcher.prototype.fetch = td.func() ReverseBlockFetcher.prototype.clear = td.func() ReverseBlockFetcher.prototype.destroy = td.func() - td.replace('../../lib/sync/fetcher', { ReverseBlockFetcher }) + td.replace('../../lib/sync/fetcher', { ReverseBlockFetcher }) const { BeaconSynchronizer } = await import('../../lib/sync/beaconsync') diff --git a/packages/client/test/sync/fetcher/headerfetcher.spec.ts b/packages/client/test/sync/fetcher/headerfetcher.spec.ts index 3b84f04568..e4c546850f 100644 --- a/packages/client/test/sync/fetcher/headerfetcher.spec.ts +++ b/packages/client/test/sync/fetcher/headerfetcher.spec.ts @@ -12,7 +12,7 @@ tape('[HeaderFetcher]', async (t) => { } PeerPool.prototype.idle = td.func() PeerPool.prototype.ban = td.func() - td.replace('../../lib/net/peerpool', { PeerPool }) + td.replace('../../lib/net/peerpool', { PeerPool }) const { HeaderFetcher } = await import('../../../lib/sync/fetcher/headerfetcher') diff --git a/packages/client/test/sync/fullsync.spec.ts b/packages/client/test/sync/fullsync.spec.ts index 840d5b80fb..a3e97d2456 100644 --- a/packages/client/test/sync/fullsync.spec.ts +++ b/packages/client/test/sync/fullsync.spec.ts @@ -26,7 +26,7 @@ tape('[FullSynchronizer]', async (t) => { BlockFetcher.prototype.fetch = td.func() BlockFetcher.prototype.clear = td.func() BlockFetcher.prototype.destroy = td.func() - td.replace('../../lib/sync/fetcher', { BlockFetcher }) + td.replace('../../lib/sync/fetcher', { BlockFetcher }) const { FullSynchronizer } = await import('../../lib/sync/fullsync') diff --git a/packages/client/test/sync/lightsync.spec.ts b/packages/client/test/sync/lightsync.spec.ts index 955f859ff6..d1de94cb40 100644 --- a/packages/client/test/sync/lightsync.spec.ts +++ b/packages/client/test/sync/lightsync.spec.ts @@ -19,7 +19,7 @@ tape('[LightSynchronizer]', async (t) => { destroy() {} } HeaderFetcher.prototype.fetch = td.func() - td.replace('../../lib/sync/fetcher', { HeaderFetcher }) + td.replace('../../lib/sync/fetcher', { HeaderFetcher }) const { LightSynchronizer } = await import('../../lib/sync/lightsync') diff --git a/packages/client/test/sync/skeleton.spec.ts b/packages/client/test/sync/skeleton.spec.ts index 65742d87dc..2a0d8ab5ed 100644 --- a/packages/client/test/sync/skeleton.spec.ts +++ b/packages/client/test/sync/skeleton.spec.ts @@ -845,7 +845,7 @@ tape('[Skeleton] / setHead', async (t) => { const originalValidate = BlockHeader.prototype._consensusFormatValidation BlockHeader.prototype._consensusFormatValidation = td.func() - td.replace('@ethereumjs/block', { BlockHeader }) + td.replace('@ethereumjs/block', { BlockHeader }) await chain.open() const genesisBlock = await chain.getBlock(BigInt(0)) diff --git a/packages/client/test/sync/snapsync.spec.ts b/packages/client/test/sync/snapsync.spec.ts index 8ca66bfbd1..eb8b5c90f1 100644 --- a/packages/client/test/sync/snapsync.spec.ts +++ b/packages/client/test/sync/snapsync.spec.ts @@ -34,7 +34,7 @@ tape('[SnapSynchronizer]', async (t) => { AccountFetcher.prototype.fetch = td.func() AccountFetcher.prototype.clear = td.func() AccountFetcher.prototype.destroy = td.func() - td.replace('../../lib/sync/fetcher', { AccountFetcher }) + td.replace('../../lib/sync/fetcher', { AccountFetcher }) const { SnapSynchronizer } = await import('../../lib/sync/snapsync') diff --git a/packages/statemanager/src/ethersStateManager.ts b/packages/statemanager/src/ethersStateManager.ts index 5e40097d6c..1cc930c3ae 100644 --- a/packages/statemanager/src/ethersStateManager.ts +++ b/packages/statemanager/src/ethersStateManager.ts @@ -7,7 +7,12 @@ import { ethers } from 'ethers' import { AccountCache, CacheType, StorageCache } from './cache' import type { Proof } from '.' -import type { AccountFields, StateManagerInterface, StorageDump } from '@ethereumjs/common' +import type { + AccessList, + AccountFields, + EVMStateManagerInterface, + StorageDump, +} from '@ethereumjs/common' import type { Address } from '@ethereumjs/util' const log = debug('statemanager') @@ -17,7 +22,7 @@ export interface EthersStateManagerOpts { blockTag: bigint | 'earliest' } -export class EthersStateManager implements StateManagerInterface { +export class EthersStateManager implements EVMStateManagerInterface { private provider: ethers.providers.StaticJsonRpcProvider | ethers.providers.JsonRpcProvider private contractCache: Map private storageCache: StorageCache @@ -335,4 +340,38 @@ export class EthersStateManager implements StateManagerInterface { hasStateRoot = () => { throw new Error('function not implemented') } + + accountIsEmptyOrNonExistent(_address: Address): Promise { + throw new Error('function not implemented') + } + getOriginalContractStorage(_address: Address, _key: Uint8Array): Promise { + throw new Error('function not implemented') + } + clearWarmedAccounts(): void { + // throw new Error('function not implemented') + } + cleanupTouchedAccounts(): Promise { + return Promise.resolve() + } + clearOriginalStorageCache(): void { + // throw new Error('function not implemented') + } + addWarmedAddress(address: Uint8Array): void { + // throw new Error('function not implemented') + } + isWarmedAddress(address: Uint8Array): boolean { + throw new Error('function not implemented') + } + addWarmedStorage(address: Uint8Array, slot: Uint8Array): void { + // throw new Error('function not implemented') + } + isWarmedStorage(address: Uint8Array, slot: Uint8Array): boolean { + throw new Error('function not implemented') + } + generateCanonicalGenesis(_initState: any): Promise { + return Promise.resolve() + } + generateAccessList(addressesRemoved: Address[], addressesOnlyStorage: Address[]): AccessList { + throw new Error('function not implemented') + } } diff --git a/packages/statemanager/test/ethersStateManager.spec.ts b/packages/statemanager/test/ethersStateManager.spec.ts index d19231349f..c1ca52d6a3 100644 --- a/packages/statemanager/test/ethersStateManager.spec.ts +++ b/packages/statemanager/test/ethersStateManager.spec.ts @@ -1,13 +1,18 @@ import { Block } from '@ethereumjs/block' +import { Chain, Common, Hardfork } from '@ethereumjs/common' +import { FeeMarketEIP1559Transaction, TransactionFactory } from '@ethereumjs/tx' import { Account, Address, bigIntToBytes, equalsBytes, + hexStringToBytes, setLengthLeft, utf8ToBytes, } from '@ethereumjs/util' +import { VM } from '@ethereumjs/vm' import { BaseProvider, StaticJsonRpcProvider } from '@ethersproject/providers' +import { ethers } from 'ethers' import * as tape from 'tape' import { EthersStateManager } from '../src/ethersStateManager' @@ -173,7 +178,6 @@ tape('Ethers State Manager API tests', async (t) => { } }) -/* TODO FIXME tape('runTx custom transaction test', async (t) => { if (isBrowser() === true) { // The `MockProvider` is not able to load JSON files dynamically in browser so skipped in browser tests @@ -216,7 +220,7 @@ tape('runTx test: replay mainnet transactions', async (t) => { const provider = process.env.PROVIDER !== undefined - ? new JsonRpcProvider(process.env.PROVIDER) + ? new ethers.providers.JsonRpcProvider(process.env.PROVIDER) : new MockProvider() const blockTag = 15496077n @@ -243,7 +247,7 @@ tape('runBlock test', async (t) => { const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Chainstart }) const provider = process.env.PROVIDER !== undefined - ? new JsonRpcProvider(process.env.PROVIDER) + ? new ethers.providers.JsonRpcProvider(process.env.PROVIDER) : new MockProvider() const blockTag = 500000n const state = new EthersStateManager({ @@ -271,4 +275,3 @@ tape('runBlock test', async (t) => { } } }) -*/ From 19cfe05e2a79612837e1f14bb6068396c7102468 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Fri, 14 Apr 2023 15:45:42 +0200 Subject: [PATCH 40/53] Update ethereum-cryptography from 1.2 to 2.0 (#2641) --- package-lock.json | 267 +++++++++++------------------ packages/block/package.json | 2 +- packages/blockchain/package.json | 2 +- packages/client/package.json | 2 +- packages/devp2p/package.json | 2 +- packages/devp2p/src/dpt/dpt.ts | 4 +- packages/devp2p/src/rlpx/ecies.ts | 6 +- packages/devp2p/src/rlpx/rlpx.ts | 4 +- packages/devp2p/src/util.ts | 6 +- packages/ethash/package.json | 2 +- packages/evm/package.json | 2 +- packages/statemanager/package.json | 4 +- packages/trie/package.json | 2 +- packages/tx/package.json | 2 +- packages/util/package.json | 2 +- packages/util/src/account.ts | 14 +- packages/util/src/constants.ts | 6 +- packages/util/src/signature.ts | 19 +- packages/vm/package.json | 2 +- 19 files changed, 141 insertions(+), 209 deletions(-) diff --git a/package-lock.json b/package-lock.json index 4967ee9850..f14e37f266 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1700,8 +1700,7 @@ }, "node_modules/@chainsafe/as-sha256": { "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@chainsafe/as-sha256/-/as-sha256-0.4.0.tgz", - "integrity": "sha512-2bFmA0JLDAXZqrmOQqrri0aeAgfdpk/kPays862raEG80nr45gyDM1BfI+HeaAvQMWgBDGoqAdFJTSb6+/DdeQ==" + "license": "Apache-2.0" }, "node_modules/@chainsafe/libp2p-noise": { "version": "4.1.2", @@ -1767,28 +1766,15 @@ }, "node_modules/@chainsafe/persistent-merkle-tree": { "version": "0.6.0", - "resolved": "https://registry.npmjs.org/@chainsafe/persistent-merkle-tree/-/persistent-merkle-tree-0.6.0.tgz", - "integrity": "sha512-OHDu/ZyjbsSHBTr2fbkeZG2qWfBvLrSJweCNwPsTcngi62Z7xaI0bLtBH69Q1QuvOYzJd2eNqseq5a58SZE1Xw==", + "license": "Apache-2.0", "dependencies": { "@chainsafe/as-sha256": "^0.4.0", "@noble/hashes": "^1.3.0" } }, - "node_modules/@chainsafe/persistent-merkle-tree/node_modules/@noble/hashes": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.0.tgz", - "integrity": "sha512-ilHEACi9DwqJB0pw7kv+Apvh50jiiSyR/cQ3y4W7lOR5mhvn/50FLUfsnfJz0BDZtl/RR16kXvptiv6q1msYZg==", - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ] - }, "node_modules/@chainsafe/ssz": { "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@chainsafe/ssz/-/ssz-0.11.0.tgz", - "integrity": "sha512-osjFURtWTk3QH73bEoU9E7XTQmYHmX+dm24btUEoaTMyaKEhaMhI0Q98BYe8M/wTdxarUV7+f2A05Im5gHlk0w==", + "license": "Apache-2.0", "dependencies": { "@chainsafe/as-sha256": "^0.4.0", "@chainsafe/persistent-merkle-tree": "^0.6.0" @@ -2767,18 +2753,6 @@ "@jridgewell/sourcemap-codec": "1.4.14" } }, - "node_modules/@lmdb/lmdb-darwin-arm64": { - "version": "2.6.8", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, "node_modules/@motrix/nat-api": { "version": "0.3.2", "license": "MIT", @@ -2794,22 +2768,24 @@ "node": ">=10.0.0" } }, - "node_modules/@msgpackr-extract/msgpackr-extract-darwin-arm64": { - "version": "2.1.2", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, "node_modules/@multiformats/base-x": { "version": "4.0.1", "license": "MIT" }, + "node_modules/@noble/curves": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.0.0.tgz", + "integrity": "sha512-2upgEu0iLiDVDZkNLeFV2+ht0BAVgQnEmCk6JsOch9Rp8xfkMCbvbAZlA2pBHQc73dbl+vFOXfqkf4uemdn0bw==", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "@noble/hashes": "1.3.0" + } + }, "node_modules/@noble/ed25519": { "version": "1.7.1", "funding": [ @@ -2821,14 +2797,15 @@ "license": "MIT" }, "node_modules/@noble/hashes": { - "version": "1.1.2", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.0.tgz", + "integrity": "sha512-ilHEACi9DwqJB0pw7kv+Apvh50jiiSyR/cQ3y4W7lOR5mhvn/50FLUfsnfJz0BDZtl/RR16kXvptiv6q1msYZg==", "funding": [ { "type": "individual", "url": "https://paulmillr.com/funding/" } - ], - "license": "MIT" + ] }, "node_modules/@noble/secp256k1": { "version": "1.6.3", @@ -2927,31 +2904,33 @@ "license": "MIT" }, "node_modules/@scure/bip32": { - "version": "1.1.0", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.3.0.tgz", + "integrity": "sha512-bcKpo1oj54hGholplGLpqPHRbIsnbixFtc06nwuNM5/dwSXOq/AAYoIBRsBmnZJSdfeNW5rnff7NTAz3ZCqR9Q==", "funding": [ { "type": "individual", "url": "https://paulmillr.com/funding/" } ], - "license": "MIT", "dependencies": { - "@noble/hashes": "~1.1.1", - "@noble/secp256k1": "~1.6.0", + "@noble/curves": "~1.0.0", + "@noble/hashes": "~1.3.0", "@scure/base": "~1.1.0" } }, "node_modules/@scure/bip39": { - "version": "1.1.0", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.2.0.tgz", + "integrity": "sha512-SX/uKq52cuxm4YFXWFaVByaSHJh2w3BnokVSeUJVCv6K7WulT9u2BuNRBhuFl8vAuYnzx9bEu9WgpcNYTrYieg==", "funding": [ { "type": "individual", "url": "https://paulmillr.com/funding/" } ], - "license": "MIT", "dependencies": { - "@noble/hashes": "~1.1.1", + "@noble/hashes": "~1.3.0", "@scure/base": "~1.1.0" } }, @@ -3358,18 +3337,16 @@ }, "node_modules/@types/yargs": { "version": "17.0.24", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.24.tgz", - "integrity": "sha512-6i0aC7jV6QzQB8ne1joVZ0eSFIstHsCrobmOtghM11yGlH0j43FKL2UhWdELkyps0zuf7qVTUVCCR+tgSlyLLw==", "dev": true, + "license": "MIT", "dependencies": { "@types/yargs-parser": "*" } }, "node_modules/@types/yargs-parser": { "version": "21.0.0", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", - "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "5.33.1", @@ -4842,9 +4819,7 @@ }, "node_modules/c-kzg": { "version": "2.0.4", - "resolved": "https://registry.npmjs.org/c-kzg/-/c-kzg-2.0.4.tgz", - "integrity": "sha512-DsHrUSUIvC/k8TuHDTLddMGYBTYfcleyoIjv9k5iv4kJTI4J6gkntEocjKbKDCmohrwms0N4QYqx1ugp3RY3FQ==", - "hasInstallScript": true, + "license": "MIT", "dependencies": { "bindings": "^1.5.0", "node-addon-api": "^5.0.0" @@ -4852,8 +4827,7 @@ }, "node_modules/c-kzg/node_modules/node-addon-api": { "version": "5.1.0", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", - "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==" + "license": "MIT" }, "node_modules/c8": { "version": "7.12.0", @@ -7191,13 +7165,14 @@ } }, "node_modules/ethereum-cryptography": { - "version": "1.1.2", - "license": "MIT", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-2.0.0.tgz", + "integrity": "sha512-g25m4EtfQGjstWgVE1aIz7XYYjf3kH5kG17ULWVB5dH6uLahsoltOhACzSxyDV+fhn4gbR4xRrOXGe6r2uh4Bg==", "dependencies": { - "@noble/hashes": "1.1.2", - "@noble/secp256k1": "1.6.3", - "@scure/bip32": "1.1.0", - "@scure/bip39": "1.1.0" + "@noble/curves": "1.0.0", + "@noble/hashes": "1.3.0", + "@scure/bip32": "1.3.0", + "@scure/bip39": "1.2.0" } }, "node_modules/ethers": { @@ -7742,18 +7717,6 @@ "dev": true, "license": "ISC" }, - "node_modules/fsevents": { - "version": "2.3.2", - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, "node_modules/function-bind": { "version": "1.1.1", "license": "MIT" @@ -11804,8 +11767,7 @@ }, "node_modules/lru-cache": { "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "license": "ISC", "engines": { "node": ">=12" } @@ -14202,9 +14164,8 @@ }, "node_modules/quibble": { "version": "0.6.17", - "resolved": "https://registry.npmjs.org/quibble/-/quibble-0.6.17.tgz", - "integrity": "sha512-uybGnGrx1hAhBCmzmVny+ycKaS5F71+q+iWVzbf8x/HyeEMDGeiQFVjWl1zhi4rwfTHa05+/NIExC4L5YRNPjQ==", "dev": true, + "license": "MIT", "dependencies": { "lodash": "^4.17.21", "resolve": "^1.22.1" @@ -16533,9 +16494,8 @@ }, "node_modules/testdouble": { "version": "3.17.2", - "resolved": "https://registry.npmjs.org/testdouble/-/testdouble-3.17.2.tgz", - "integrity": "sha512-oRrk1DJISNoFr3aaczIqrrhkOUQ26BsXN3SopYT/U0GTvk9hlKPCEbd9R2uxkcufKZgEfo9D1JAB4CJrjHE9cw==", "dev": true, + "license": "MIT", "dependencies": { "lodash": "^4.17.21", "quibble": "^0.6.17", @@ -17831,7 +17791,7 @@ "@ethereumjs/trie": "^5.0.4", "@ethereumjs/tx": "^4.1.1", "@ethereumjs/util": "^8.0.5", - "ethereum-cryptography": "^1.1.2" + "ethereum-cryptography": "^2.0.0" }, "devDependencies": { "c-kzg": "^2.0.4", @@ -17854,7 +17814,7 @@ "@ethereumjs/tx": "^4.1.1", "@ethereumjs/util": "^8.0.5", "debug": "^4.3.3", - "ethereum-cryptography": "^1.1.2", + "ethereum-cryptography": "^2.0.0", "level": "^8.0.0", "lru-cache": "^7.18.3" }, @@ -17892,7 +17852,7 @@ "connect": "^3.7.0", "cors": "^2.8.5", "debug": "^4.3.3", - "ethereum-cryptography": "^1.1.2", + "ethereum-cryptography": "^2.0.0", "fs-extra": "^10.1.0", "it-pipe": "^1.1.0", "jayson": "^4.0.0", @@ -17980,8 +17940,7 @@ }, "packages/client/node_modules/yargs": { "version": "17.7.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.1.tgz", - "integrity": "sha512-cwiTb08Xuv5fqF4AovYacTFNxk62th7LKJ6BL9IGUpTJrWoU7/7WdQGTP2SjKf1dUNBGzDd28p/Yfs/GI6JrLw==", + "license": "MIT", "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", @@ -18022,7 +17981,7 @@ "@scure/base": "1.1.1", "@types/k-bucket": "^5.0.0", "debug": "^4.3.3", - "ethereum-cryptography": "^1.1.2", + "ethereum-cryptography": "^2.0.0", "k-bucket": "^5.0.0", "lru-cache": "^7.18.3", "ms": "^0.7.1", @@ -18109,7 +18068,7 @@ "@ethereumjs/rlp": "^4.0.1", "@ethereumjs/util": "^8.0.5", "bigint-crypto-utils": "^3.0.23", - "ethereum-cryptography": "^1.1.2" + "ethereum-cryptography": "^2.0.0" }, "devDependencies": { "@ethereumjs/common": "^3.1.1" @@ -18127,7 +18086,7 @@ "@ethereumjs/statemanager": "^1.0.4", "@ethereumjs/util": "^8.0.5", "debug": "^4.3.3", - "ethereum-cryptography": "^1.1.2", + "ethereum-cryptography": "^2.0.0", "mcl-wasm": "^0.7.1", "rustbn.js": "~0.2.0" }, @@ -18169,7 +18128,7 @@ "@ethereumjs/common": "^3.1.1", "@ethereumjs/rlp": "^4.0.1", "debug": "^4.3.3", - "ethereum-cryptography": "^1.1.2", + "ethereum-cryptography": "^2.0.0", "ethers": "^5.7.1", "js-sdsl": "^4.1.4", "lru-cache": "^7.18.3" @@ -18182,7 +18141,7 @@ "@types/tape": "^4.13.2", "debug": "^4.3.3", "eslint": "^8.0.0", - "ethereum-cryptography": "^1.1.2", + "ethereum-cryptography": "^2.0.0", "functional-red-black-tree": "^1.0.1", "karma": "^6.3.2", "karma-chrome-launcher": "^3.1.0", @@ -18204,7 +18163,7 @@ "@ethereumjs/rlp": "^4.0.1", "@ethereumjs/util": "^8.0.5", "@types/readable-stream": "^2.3.13", - "ethereum-cryptography": "^1.1.2", + "ethereum-cryptography": "^2.0.0", "lru-cache": "^7.18.3", "readable-stream": "^3.6.0" }, @@ -18245,7 +18204,7 @@ "@ethereumjs/common": "^3.1.1", "@ethereumjs/rlp": "^4.0.1", "@ethereumjs/util": "^8.0.5", - "ethereum-cryptography": "^1.1.2" + "ethereum-cryptography": "^2.0.0" }, "devDependencies": { "@types/minimist": "^1.2.0", @@ -18273,7 +18232,7 @@ "dependencies": { "@chainsafe/ssz": "^0.11.0", "@ethereumjs/rlp": "^4.0.1", - "ethereum-cryptography": "^1.1.2" + "ethereum-cryptography": "^2.0.0" }, "devDependencies": { "@types/bn.js": "^5.1.0", @@ -18306,7 +18265,7 @@ "@ethereumjs/tx": "^4.1.1", "@ethereumjs/util": "^8.0.5", "debug": "^4.3.3", - "ethereum-cryptography": "^1.1.2", + "ethereum-cryptography": "^2.0.0", "mcl-wasm": "^0.7.1", "rustbn.js": "~0.2.0" }, @@ -19411,9 +19370,7 @@ "dev": true }, "@chainsafe/as-sha256": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@chainsafe/as-sha256/-/as-sha256-0.4.0.tgz", - "integrity": "sha512-2bFmA0JLDAXZqrmOQqrri0aeAgfdpk/kPays862raEG80nr45gyDM1BfI+HeaAvQMWgBDGoqAdFJTSb6+/DdeQ==" + "version": "0.4.0" }, "@chainsafe/libp2p-noise": { "version": "4.1.2", @@ -19470,24 +19427,13 @@ }, "@chainsafe/persistent-merkle-tree": { "version": "0.6.0", - "resolved": "https://registry.npmjs.org/@chainsafe/persistent-merkle-tree/-/persistent-merkle-tree-0.6.0.tgz", - "integrity": "sha512-OHDu/ZyjbsSHBTr2fbkeZG2qWfBvLrSJweCNwPsTcngi62Z7xaI0bLtBH69Q1QuvOYzJd2eNqseq5a58SZE1Xw==", "requires": { "@chainsafe/as-sha256": "^0.4.0", "@noble/hashes": "^1.3.0" - }, - "dependencies": { - "@noble/hashes": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.0.tgz", - "integrity": "sha512-ilHEACi9DwqJB0pw7kv+Apvh50jiiSyR/cQ3y4W7lOR5mhvn/50FLUfsnfJz0BDZtl/RR16kXvptiv6q1msYZg==" - } } }, "@chainsafe/ssz": { "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@chainsafe/ssz/-/ssz-0.11.0.tgz", - "integrity": "sha512-osjFURtWTk3QH73bEoU9E7XTQmYHmX+dm24btUEoaTMyaKEhaMhI0Q98BYe8M/wTdxarUV7+f2A05Im5gHlk0w==", "requires": { "@chainsafe/as-sha256": "^0.4.0", "@chainsafe/persistent-merkle-tree": "^0.6.0" @@ -19549,7 +19495,7 @@ "@ethereumjs/tx": "^4.1.1", "@ethereumjs/util": "^8.0.5", "c-kzg": "^2.0.4", - "ethereum-cryptography": "^1.1.2", + "ethereum-cryptography": "^2.0.0", "testdouble": "^3.17.2" } }, @@ -19566,7 +19512,7 @@ "@types/async": "^2.4.1", "@types/level-errors": "^3.0.0", "debug": "^4.3.3", - "ethereum-cryptography": "^1.1.2", + "ethereum-cryptography": "^2.0.0", "level": "^8.0.0", "lru-cache": "^7.18.3" } @@ -19601,7 +19547,7 @@ "cors": "^2.8.5", "crypto-browserify": "^3.12.0", "debug": "^4.3.3", - "ethereum-cryptography": "^1.1.2", + "ethereum-cryptography": "^2.0.0", "file-replace-loader": "^1.2.0", "fs-extra": "^10.1.0", "it-pair": "^1.0.0", @@ -19661,8 +19607,6 @@ }, "yargs": { "version": "17.7.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.1.tgz", - "integrity": "sha512-cwiTb08Xuv5fqF4AovYacTFNxk62th7LKJ6BL9IGUpTJrWoU7/7WdQGTP2SjKf1dUNBGzDd28p/Yfs/GI6JrLw==", "requires": { "cliui": "^8.0.1", "escalade": "^3.1.1", @@ -19701,7 +19645,7 @@ "@types/ms": "^0.7.30", "chalk": "^2.4.2", "debug": "^4.3.3", - "ethereum-cryptography": "^1.1.2", + "ethereum-cryptography": "^2.0.0", "k-bucket": "^5.0.0", "lru-cache": "^7.18.3", "ms": "^0.7.1", @@ -19759,7 +19703,7 @@ "@ethereumjs/rlp": "^4.0.1", "@ethereumjs/util": "^8.0.5", "bigint-crypto-utils": "^3.0.23", - "ethereum-cryptography": "^1.1.2" + "ethereum-cryptography": "^2.0.0" } }, "@ethereumjs/evm": { @@ -19776,7 +19720,7 @@ "benchmark": "^2.1.4", "c-kzg": "^2.0.4", "debug": "^4.3.3", - "ethereum-cryptography": "^1.1.2", + "ethereum-cryptography": "^2.0.0", "level": "^8.0.0", "mcl-wasm": "^0.7.1", "memory-level": "^1.0.0", @@ -19801,7 +19745,7 @@ "@types/tape": "^4.13.2", "debug": "^4.3.3", "eslint": "^8.0.0", - "ethereum-cryptography": "^1.1.2", + "ethereum-cryptography": "^2.0.0", "ethers": "^5.7.1", "functional-red-black-tree": "^1.0.1", "js-sdsl": "^4.1.4", @@ -19827,7 +19771,7 @@ "@types/readable-stream": "^2.3.13", "0x": "^4.9.1", "abstract-level": "^1.0.3", - "ethereum-cryptography": "^1.1.2", + "ethereum-cryptography": "^2.0.0", "level": "^8.0.0", "level-legacy": "npm:level@^7.0.0", "level-mem": "^6.0.1", @@ -19858,7 +19802,7 @@ "@ethereumjs/util": "^8.0.5", "@types/minimist": "^1.2.0", "@types/node-dir": "^0.0.34", - "ethereum-cryptography": "^1.1.2", + "ethereum-cryptography": "^2.0.0", "minimist": "^1.2.0", "node-dir": "^0.1.16", "testdouble": "^3.17.2" @@ -19871,7 +19815,7 @@ "@ethereumjs/rlp": "^4.0.1", "@types/bn.js": "^5.1.0", "@types/secp256k1": "^4.0.1", - "ethereum-cryptography": "^1.1.2" + "ethereum-cryptography": "^2.0.0" } }, "@ethereumjs/vm": { @@ -19894,7 +19838,7 @@ "benchmark": "^2.1.4", "c-kzg": "^2.0.4", "debug": "^4.3.3", - "ethereum-cryptography": "^1.1.2", + "ethereum-cryptography": "^2.0.0", "mcl-wasm": "^0.7.1", "minimist": "^1.2.5", "node-dir": "^0.1.17", @@ -20397,11 +20341,6 @@ "@jridgewell/sourcemap-codec": "1.4.14" } }, - "@lmdb/lmdb-darwin-arm64": { - "version": "2.6.8", - "dev": true, - "optional": true - }, "@motrix/nat-api": { "version": "0.3.2", "requires": { @@ -20413,19 +20352,24 @@ "xml2js": "^0.4.23" } }, - "@msgpackr-extract/msgpackr-extract-darwin-arm64": { - "version": "2.1.2", - "dev": true, - "optional": true - }, "@multiformats/base-x": { "version": "4.0.1" }, + "@noble/curves": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.0.0.tgz", + "integrity": "sha512-2upgEu0iLiDVDZkNLeFV2+ht0BAVgQnEmCk6JsOch9Rp8xfkMCbvbAZlA2pBHQc73dbl+vFOXfqkf4uemdn0bw==", + "requires": { + "@noble/hashes": "1.3.0" + } + }, "@noble/ed25519": { "version": "1.7.1" }, "@noble/hashes": { - "version": "1.1.2" + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.0.tgz", + "integrity": "sha512-ilHEACi9DwqJB0pw7kv+Apvh50jiiSyR/cQ3y4W7lOR5mhvn/50FLUfsnfJz0BDZtl/RR16kXvptiv6q1msYZg==" }, "@noble/secp256k1": { "version": "1.6.3" @@ -20488,17 +20432,21 @@ "version": "1.1.1" }, "@scure/bip32": { - "version": "1.1.0", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.3.0.tgz", + "integrity": "sha512-bcKpo1oj54hGholplGLpqPHRbIsnbixFtc06nwuNM5/dwSXOq/AAYoIBRsBmnZJSdfeNW5rnff7NTAz3ZCqR9Q==", "requires": { - "@noble/hashes": "~1.1.1", - "@noble/secp256k1": "~1.6.0", + "@noble/curves": "~1.0.0", + "@noble/hashes": "~1.3.0", "@scure/base": "~1.1.0" } }, "@scure/bip39": { - "version": "1.1.0", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.2.0.tgz", + "integrity": "sha512-SX/uKq52cuxm4YFXWFaVByaSHJh2w3BnokVSeUJVCv6K7WulT9u2BuNRBhuFl8vAuYnzx9bEu9WgpcNYTrYieg==", "requires": { - "@noble/hashes": "~1.1.1", + "@noble/hashes": "~1.3.0", "@scure/base": "~1.1.0" } }, @@ -20843,8 +20791,6 @@ }, "@types/yargs": { "version": "17.0.24", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.24.tgz", - "integrity": "sha512-6i0aC7jV6QzQB8ne1joVZ0eSFIstHsCrobmOtghM11yGlH0j43FKL2UhWdELkyps0zuf7qVTUVCCR+tgSlyLLw==", "dev": true, "requires": { "@types/yargs-parser": "*" @@ -20852,8 +20798,6 @@ }, "@types/yargs-parser": { "version": "21.0.0", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", - "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", "dev": true }, "@typescript-eslint/eslint-plugin": { @@ -21862,17 +21806,13 @@ }, "c-kzg": { "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": { "node-addon-api": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", - "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==" + "version": "5.1.0" } } }, @@ -23511,12 +23451,14 @@ "dev": true }, "ethereum-cryptography": { - "version": "1.1.2", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-2.0.0.tgz", + "integrity": "sha512-g25m4EtfQGjstWgVE1aIz7XYYjf3kH5kG17ULWVB5dH6uLahsoltOhACzSxyDV+fhn4gbR4xRrOXGe6r2uh4Bg==", "requires": { - "@noble/hashes": "1.1.2", - "@noble/secp256k1": "1.6.3", - "@scure/bip32": "1.1.0", - "@scure/bip39": "1.1.0" + "@noble/curves": "1.0.0", + "@noble/hashes": "1.3.0", + "@scure/bip32": "1.3.0", + "@scure/bip39": "1.2.0" } }, "ethers": { @@ -23879,11 +23821,6 @@ "version": "1.0.0", "dev": true }, - "fsevents": { - "version": "2.3.2", - "dev": true, - "optional": true - }, "function-bind": { "version": "1.1.1" }, @@ -26675,9 +26612,7 @@ "dev": true }, "lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==" + "version": "7.18.3" }, "ltgt": { "version": "2.2.1", @@ -28265,8 +28200,6 @@ }, "quibble": { "version": "0.6.17", - "resolved": "https://registry.npmjs.org/quibble/-/quibble-0.6.17.tgz", - "integrity": "sha512-uybGnGrx1hAhBCmzmVny+ycKaS5F71+q+iWVzbf8x/HyeEMDGeiQFVjWl1zhi4rwfTHa05+/NIExC4L5YRNPjQ==", "dev": true, "requires": { "lodash": "^4.17.21", @@ -29848,8 +29781,6 @@ }, "testdouble": { "version": "3.17.2", - "resolved": "https://registry.npmjs.org/testdouble/-/testdouble-3.17.2.tgz", - "integrity": "sha512-oRrk1DJISNoFr3aaczIqrrhkOUQ26BsXN3SopYT/U0GTvk9hlKPCEbd9R2uxkcufKZgEfo9D1JAB4CJrjHE9cw==", "dev": true, "requires": { "lodash": "^4.17.21", diff --git a/packages/block/package.json b/packages/block/package.json index 373eac03d1..e2a91ea7c2 100644 --- a/packages/block/package.json +++ b/packages/block/package.json @@ -43,7 +43,7 @@ "@ethereumjs/trie": "^5.0.4", "@ethereumjs/tx": "^4.1.1", "@ethereumjs/util": "^8.0.5", - "ethereum-cryptography": "^1.1.2" + "ethereum-cryptography": "^2.0.0" }, "devDependencies": { "c-kzg": "^2.0.4", diff --git a/packages/blockchain/package.json b/packages/blockchain/package.json index 54feaa8aa7..737c15ab09 100644 --- a/packages/blockchain/package.json +++ b/packages/blockchain/package.json @@ -46,7 +46,7 @@ "@ethereumjs/tx": "^4.1.1", "@ethereumjs/util": "^8.0.5", "debug": "^4.3.3", - "ethereum-cryptography": "^1.1.2", + "ethereum-cryptography": "^2.0.0", "level": "^8.0.0", "lru-cache": "^7.18.3" }, diff --git a/packages/client/package.json b/packages/client/package.json index 174248e1b5..a20e949c01 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -77,7 +77,7 @@ "connect": "^3.7.0", "cors": "^2.8.5", "debug": "^4.3.3", - "ethereum-cryptography": "^1.1.2", + "ethereum-cryptography": "^2.0.0", "fs-extra": "^10.1.0", "it-pipe": "^1.1.0", "jayson": "^4.0.0", diff --git a/packages/devp2p/package.json b/packages/devp2p/package.json index 7896a615eb..3664f7a678 100644 --- a/packages/devp2p/package.json +++ b/packages/devp2p/package.json @@ -55,7 +55,7 @@ "@scure/base": "1.1.1", "@types/k-bucket": "^5.0.0", "debug": "^4.3.3", - "ethereum-cryptography": "^1.1.2", + "ethereum-cryptography": "^2.0.0", "k-bucket": "^5.0.0", "lru-cache": "^7.18.3", "ms": "^0.7.1", diff --git a/packages/devp2p/src/dpt/dpt.ts b/packages/devp2p/src/dpt/dpt.ts index 224730c6ff..b6509e6eb5 100644 --- a/packages/devp2p/src/dpt/dpt.ts +++ b/packages/devp2p/src/dpt/dpt.ts @@ -1,5 +1,5 @@ import { bytesToInt, randomBytes } from '@ethereumjs/util' -import { getPublicKey } from 'ethereum-cryptography/secp256k1' +import { secp256k1 } from 'ethereum-cryptography/secp256k1' import { EventEmitter } from 'events' import ms = require('ms') @@ -107,7 +107,7 @@ export class DPT extends EventEmitter { super() this.privateKey = privateKey - this._id = pk2id(getPublicKey(this.privateKey, false)) + this._id = pk2id(secp256k1.getPublicKey(this.privateKey, false)) this._shouldFindNeighbours = options.shouldFindNeighbours ?? true this._shouldGetDnsPeers = options.shouldGetDnsPeers ?? false // By default, tries to connect to 12 new peers every 3s diff --git a/packages/devp2p/src/rlpx/ecies.ts b/packages/devp2p/src/rlpx/ecies.ts index 5c7e540042..c96e31540c 100644 --- a/packages/devp2p/src/rlpx/ecies.ts +++ b/packages/devp2p/src/rlpx/ecies.ts @@ -3,7 +3,7 @@ import { bytesToInt, concatBytes, intToBytes } from '@ethereumjs/util' import * as crypto from 'crypto' import { debug as createDebugLogger } from 'debug' import { getRandomBytesSync } from 'ethereum-cryptography/random' -import { getPublicKey } from 'ethereum-cryptography/secp256k1' +import { secp256k1 } from 'ethereum-cryptography/secp256k1' import { ecdh, ecdsaRecover, ecdsaSign } from 'ethereum-cryptography/secp256k1-compat' import { hexToBytes } from 'ethereum-cryptography/utils' @@ -84,7 +84,7 @@ export class ECIES { this._nonce = getRandomBytesSync(32) this._ephemeralPrivateKey = genPrivateKey() - this._ephemeralPublicKey = getPublicKey(this._ephemeralPrivateKey, false) + this._ephemeralPublicKey = secp256k1.getPublicKey(this._ephemeralPrivateKey, false) } _encryptMessage( @@ -112,7 +112,7 @@ export class ECIES { crypto.createHmac('sha256', mkey).update(concatBytes(dataIV, sharedMacData)).digest() ) - const publicKey = getPublicKey(privateKey, false) + const publicKey = secp256k1.getPublicKey(privateKey, false) return concatBytes(publicKey, dataIV, tag) } diff --git a/packages/devp2p/src/rlpx/rlpx.ts b/packages/devp2p/src/rlpx/rlpx.ts index f8152585ed..adbacbc975 100644 --- a/packages/devp2p/src/rlpx/rlpx.ts +++ b/packages/devp2p/src/rlpx/rlpx.ts @@ -1,6 +1,6 @@ import { bytesToInt } from '@ethereumjs/util' import { debug as createDebugLogger } from 'debug' -import { getPublicKey } from 'ethereum-cryptography/secp256k1' +import { secp256k1 } from 'ethereum-cryptography/secp256k1' import { bytesToHex, equalsBytes, hexToBytes, utf8ToBytes } from 'ethereum-cryptography/utils' import { EventEmitter } from 'events' import ms = require('ms') @@ -63,7 +63,7 @@ export class RLPx extends EventEmitter { super() this._privateKey = privateKey - this._id = pk2id(getPublicKey(this._privateKey, false)) + this._id = pk2id(secp256k1.getPublicKey(this._privateKey, false)) // options this._timeout = options.timeout ?? ms('10s') diff --git a/packages/devp2p/src/util.ts b/packages/devp2p/src/util.ts index a744dd96fd..c105ccc0d1 100644 --- a/packages/devp2p/src/util.ts +++ b/packages/devp2p/src/util.ts @@ -1,7 +1,7 @@ import { RLP } from '@ethereumjs/rlp' import { debug as createDebugLogger } from 'debug' import { keccak256 as _keccak256 } from 'ethereum-cryptography/keccak' -import { utils } from 'ethereum-cryptography/secp256k1' +import { secp256k1 } from 'ethereum-cryptography/secp256k1' import { publicKeyConvert } from 'ethereum-cryptography/secp256k1-compat' import { bytesToHex, concatBytes, equalsBytes } from 'ethereum-cryptography/utils' @@ -16,8 +16,8 @@ export function keccak256(...bytes: Uint8Array[]) { } export function genPrivateKey(): Uint8Array { - const privateKey = utils.randomPrivateKey() - return utils.isValidPrivateKey(privateKey) ? privateKey : genPrivateKey() + const privateKey = secp256k1.utils.randomPrivateKey() + return secp256k1.utils.isValidPrivateKey(privateKey) === true ? privateKey : genPrivateKey() } export function pk2id(pk: Uint8Array): Uint8Array { diff --git a/packages/ethash/package.json b/packages/ethash/package.json index 1736ef714d..3e08386147 100644 --- a/packages/ethash/package.json +++ b/packages/ethash/package.json @@ -41,7 +41,7 @@ "@ethereumjs/rlp": "^4.0.1", "@ethereumjs/util": "^8.0.5", "bigint-crypto-utils": "^3.0.23", - "ethereum-cryptography": "^1.1.2" + "ethereum-cryptography": "^2.0.0" }, "devDependencies": { "@ethereumjs/common": "^3.1.1" diff --git a/packages/evm/package.json b/packages/evm/package.json index e0ad5a7422..f1ac7cef61 100644 --- a/packages/evm/package.json +++ b/packages/evm/package.json @@ -51,7 +51,7 @@ "@ethereumjs/common": "^3.1.1", "@ethereumjs/util": "^8.0.5", "debug": "^4.3.3", - "ethereum-cryptography": "^1.1.2", + "ethereum-cryptography": "^2.0.0", "mcl-wasm": "^0.7.1", "rustbn.js": "~0.2.0" }, diff --git a/packages/statemanager/package.json b/packages/statemanager/package.json index d039f4f07c..67f3491682 100644 --- a/packages/statemanager/package.json +++ b/packages/statemanager/package.json @@ -44,7 +44,7 @@ "@ethereumjs/common": "^3.1.1", "@ethereumjs/rlp": "^4.0.1", "debug": "^4.3.3", - "ethereum-cryptography": "^1.1.2", + "ethereum-cryptography": "^2.0.0", "ethers": "^5.7.1", "js-sdsl": "^4.1.4", "lru-cache": "^7.18.3" @@ -57,7 +57,7 @@ "@types/tape": "^4.13.2", "debug": "^4.3.3", "eslint": "^8.0.0", - "ethereum-cryptography": "^1.1.2", + "ethereum-cryptography": "^2.0.0", "functional-red-black-tree": "^1.0.1", "karma": "^6.3.2", "karma-chrome-launcher": "^3.1.0", diff --git a/packages/trie/package.json b/packages/trie/package.json index df48c8ebff..135c2d84ec 100644 --- a/packages/trie/package.json +++ b/packages/trie/package.json @@ -48,8 +48,8 @@ "@ethereumjs/rlp": "^4.0.1", "@ethereumjs/util": "^8.0.5", "@types/readable-stream": "^2.3.13", - "ethereum-cryptography": "^1.1.2", "lru-cache": "^7.18.3", + "ethereum-cryptography": "^2.0.0", "readable-stream": "^3.6.0" }, "devDependencies": { diff --git a/packages/tx/package.json b/packages/tx/package.json index a5219acd39..d59b06f014 100644 --- a/packages/tx/package.json +++ b/packages/tx/package.json @@ -55,7 +55,7 @@ "@ethereumjs/common": "^3.1.1", "@ethereumjs/rlp": "^4.0.1", "@ethereumjs/util": "^8.0.5", - "ethereum-cryptography": "^1.1.2" + "ethereum-cryptography": "^2.0.0" }, "peerDependencies": { "c-kzg": "^2.0.4" diff --git a/packages/util/package.json b/packages/util/package.json index c0eda02468..eb355782bf 100644 --- a/packages/util/package.json +++ b/packages/util/package.json @@ -85,7 +85,7 @@ "dependencies": { "@chainsafe/ssz": "^0.11.0", "@ethereumjs/rlp": "^4.0.1", - "ethereum-cryptography": "^1.1.2" + "ethereum-cryptography": "^2.0.0" }, "devDependencies": { "@types/bn.js": "^5.1.0", diff --git a/packages/util/src/account.ts b/packages/util/src/account.ts index 0e326c4a27..96b54c0859 100644 --- a/packages/util/src/account.ts +++ b/packages/util/src/account.ts @@ -1,6 +1,6 @@ import { RLP } from '@ethereumjs/rlp' import { keccak256 } from 'ethereum-cryptography/keccak' -import { Point, utils } from 'ethereum-cryptography/secp256k1' +import { secp256k1 } from 'ethereum-cryptography/secp256k1' import { bytesToHex, concatBytes, @@ -245,7 +245,7 @@ export const generateAddress2 = function ( * Checks if the private key satisfies the rules of the curve secp256k1. */ export const isValidPrivate = function (privateKey: Uint8Array): boolean { - return utils.isValidPrivateKey(privateKey) + return secp256k1.utils.isValidPrivateKey(privateKey) } /** @@ -260,7 +260,7 @@ export const isValidPublic = function (publicKey: Uint8Array, sanitize: boolean // Convert to SEC1 for secp256k1 // Automatically checks whether point is on curve try { - Point.fromHex(concatBytes(Uint8Array.from([4]), publicKey)) + secp256k1.ProjectivePoint.fromHex(concatBytes(Uint8Array.from([4]), publicKey)) return true } catch (e) { return false @@ -272,7 +272,7 @@ export const isValidPublic = function (publicKey: Uint8Array, sanitize: boolean } try { - Point.fromHex(publicKey) + secp256k1.ProjectivePoint.fromHex(publicKey) return true } catch (e) { return false @@ -288,7 +288,7 @@ export const isValidPublic = function (publicKey: Uint8Array, sanitize: boolean export const pubToAddress = function (pubKey: Uint8Array, sanitize: boolean = false): Uint8Array { assertIsBytes(pubKey) if (sanitize && pubKey.length !== 64) { - pubKey = Point.fromHex(pubKey).toRawBytes(false).subarray(1) + pubKey = secp256k1.ProjectivePoint.fromHex(pubKey).toRawBytes(false).slice(1) } if (pubKey.length !== 64) { throw new Error('Expected pubKey to be of length 64') @@ -305,7 +305,7 @@ export const publicToAddress = pubToAddress export const privateToPublic = function (privateKey: Uint8Array): Uint8Array { assertIsBytes(privateKey) // skip the type flag and use the X, Y points - return Point.fromPrivateKey(privateKey).toRawBytes(false).subarray(1) + return secp256k1.ProjectivePoint.fromPrivateKey(privateKey).toRawBytes(false).slice(1) } /** @@ -322,7 +322,7 @@ export const privateToAddress = function (privateKey: Uint8Array): Uint8Array { export const importPublic = function (publicKey: Uint8Array): Uint8Array { assertIsBytes(publicKey) if (publicKey.length !== 64) { - publicKey = Point.fromHex(publicKey).toRawBytes(false).subarray(1) + publicKey = secp256k1.ProjectivePoint.fromHex(publicKey).toRawBytes(false).slice(1) } return publicKey } diff --git a/packages/util/src/constants.ts b/packages/util/src/constants.ts index ee823d9d47..83c60b538a 100644 --- a/packages/util/src/constants.ts +++ b/packages/util/src/constants.ts @@ -1,4 +1,4 @@ -import { CURVE } from 'ethereum-cryptography/secp256k1' +import { secp256k1 } from 'ethereum-cryptography/secp256k1' import { hexToBytes } from 'ethereum-cryptography/utils' /** @@ -22,8 +22,8 @@ export const MAX_INTEGER_BIGINT = BigInt( '115792089237316195423570985008687907853269984665640564039457584007913129639935' ) -export const SECP256K1_ORDER = CURVE.n -export const SECP256K1_ORDER_DIV_2 = CURVE.n / BigInt(2) +export const SECP256K1_ORDER = secp256k1.CURVE.n +export const SECP256K1_ORDER_DIV_2 = secp256k1.CURVE.n / BigInt(2) /** * 2^256 diff --git a/packages/util/src/signature.ts b/packages/util/src/signature.ts index 6ee44a1075..7d52da495a 100644 --- a/packages/util/src/signature.ts +++ b/packages/util/src/signature.ts @@ -1,5 +1,5 @@ import { keccak256 } from 'ethereum-cryptography/keccak' -import { recoverPublicKey, signSync } from 'ethereum-cryptography/secp256k1' +import { secp256k1 } from 'ethereum-cryptography/secp256k1' import { concatBytes, utf8ToBytes } from 'ethereum-cryptography/utils' import { @@ -29,15 +29,15 @@ export function ecsign( privateKey: Uint8Array, chainId?: bigint ): ECDSASignature { - const [signature, recovery] = signSync(msgHash, privateKey, { recovered: true, der: false }) - - const r = signature.subarray(0, 32) - const s = signature.subarray(32, 64) + const sig = secp256k1.sign(msgHash, privateKey) + const buf = sig.toCompactRawBytes() + const r = buf.slice(0, 32) + const s = buf.slice(32, 64) const v = chainId === undefined - ? BigInt(recovery + 27) - : BigInt(recovery + 35) + BigInt(chainId) * BigInt(2) + ? BigInt(sig.recovery! + 27) + : BigInt(sig.recovery! + 35) + BigInt(chainId) * BigInt(2) return { r, s, v } } @@ -73,8 +73,9 @@ export const ecrecover = function ( throw new Error('Invalid signature v value') } - const senderPubKey = recoverPublicKey(msgHash, signature, Number(recovery)) - return senderPubKey.subarray(1) + const sig = secp256k1.Signature.fromCompact(signature).addRecoveryBit(Number(recovery)) + const senderPubKey = sig.recoverPublicKey(msgHash) + return senderPubKey.toRawBytes(false).slice(1) } /** diff --git a/packages/vm/package.json b/packages/vm/package.json index 1c1eb18e8d..71584c942a 100644 --- a/packages/vm/package.json +++ b/packages/vm/package.json @@ -66,7 +66,7 @@ "@ethereumjs/tx": "^4.1.1", "@ethereumjs/util": "^8.0.5", "debug": "^4.3.3", - "ethereum-cryptography": "^1.1.2", + "ethereum-cryptography": "^2.0.0", "mcl-wasm": "^0.7.1", "rustbn.js": "~0.2.0" }, From bfc9baaa5e97017b4001a88de8fd6538732eef5b Mon Sep 17 00:00:00 2001 From: Holger Drewes Date: Mon, 17 Apr 2023 14:36:40 +0200 Subject: [PATCH 41/53] Monorepo: remove Node 14 from Node version GitHub actions nightly run, remove npm v7 check (#2644) --- .github/workflows/node-versions.yml | 30 +++++++++++++---------------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/.github/workflows/node-versions.yml b/.github/workflows/node-versions.yml index ffd6a1a351..a30616f682 100644 --- a/.github/workflows/node-versions.yml +++ b/.github/workflows/node-versions.yml @@ -38,10 +38,6 @@ jobs: node-version: ${{ matrix.node }} cache: 'npm' - - name: Use npm v7 for workspaces support - run: npm i -g npm@7 - if: ${{ matrix.node-version < 16 }} - - run: npm ci # Added a check to ensure we only run on NodeJS 14 or later to all jobs until the `node-testable-versions` script stops picking up 12. @@ -49,12 +45,12 @@ jobs: - name: Test Block run: npm run test working-directory: packages/block - if: ${{ matrix.node >= 14 }} + if: ${{ matrix.node >= 16 }} - name: Test Blockchain run: npm run test working-directory: packages/blockchain - if: ${{ matrix.node >= 14 }} + if: ${{ matrix.node >= 16 }} # Client and Devp2p temporarily disabled for Node < 15 due to browser build # error along node-versions CI run "TextDecoder is not defined" triggered in @@ -66,54 +62,54 @@ jobs: - name: Test Client run: npm run test:unit working-directory: packages/client - if: ${{ matrix.node >= 14 }} + if: ${{ matrix.node >= 16 }} - name: Test Devp2p run: npm run test working-directory: packages/devp2p - if: ${{ matrix.node >= 14 }} + if: ${{ matrix.node >= 16 }} - name: Test Common run: npm run test working-directory: packages/common - if: ${{ matrix.node >= 14 }} + if: ${{ matrix.node >= 16 }} - name: Test Ethash run: npm run test working-directory: packages/ethash - if: ${{ matrix.node >= 14 }} + if: ${{ matrix.node >= 16 }} - name: Test EVM run: npm run test working-directory: packages/evm - if: ${{ matrix.node >= 14 }} + if: ${{ matrix.node >= 16 }} - name: Test Trie run: npm run test working-directory: packages/trie - if: ${{ matrix.node >= 14 }} + if: ${{ matrix.node >= 16 }} - name: Test Tx run: npm run test working-directory: packages/tx - if: ${{ matrix.node >= 14 }} + if: ${{ matrix.node >= 16 }} - name: Test Util run: npm run test working-directory: packages/util - if: ${{ matrix.node >= 14 }} + if: ${{ matrix.node >= 16 }} - name: Test StateManager run: npm run test working-directory: packages/statemanager - if: ${{ matrix.node >= 14 }} + if: ${{ matrix.node >= 16 }} - name: Test VM run: npm run test:API working-directory: packages/vm - if: ${{ matrix.node >= 14 }} + if: ${{ matrix.node >= 16 }} - name: Test RLP run: npm run test working-directory: packages/rlp - if: ${{ matrix.node >= 14 }} + if: ${{ matrix.node >= 16 }} From 0678748db74d69114385b11e3a89c952abc0bc70 Mon Sep 17 00:00:00 2001 From: acolytec3 Date: Mon, 17 Apr 2023 12:55:42 -0400 Subject: [PATCH 42/53] Update package-lock --- package-lock.json | 30612 -------------------------- packages/blockchain/karma.conf.js | 2 +- packages/ethash/package.json | 2 +- packages/evm/karma.conf.js | 2 +- packages/statemanager/karma.conf.js | 2 +- packages/trie/karma.conf.js | 2 +- packages/vm/karma.conf.js | 2 +- 7 files changed, 6 insertions(+), 30618 deletions(-) delete mode 100644 package-lock.json diff --git a/package-lock.json b/package-lock.json deleted file mode 100644 index f14e37f266..0000000000 --- a/package-lock.json +++ /dev/null @@ -1,30612 +0,0 @@ -{ - "name": "root", - "lockfileVersion": 2, - "requires": true, - "packages": { - "": { - "name": "root", - "hasInstallScript": true, - "workspaces": [ - "packages/*" - ], - "devDependencies": { - "@types/node": "16.11.49", - "@types/tape": "4.13.2", - "@typescript-eslint/eslint-plugin": "5.33.1", - "@typescript-eslint/parser": "5.33.1", - "c8": "7.12.0", - "eslint": "8.22.0", - "eslint-config-prettier": "8.5.0", - "eslint-config-typestrict": "1.0.5", - "eslint-formatter-codeframe": "7.32.1", - "eslint-plugin-ethereumjs": "file:./eslint", - "eslint-plugin-github": "4.3.7", - "eslint-plugin-implicit-dependencies": "1.1.1", - "eslint-plugin-import": "2.26.0", - "eslint-plugin-prettier": "4.2.1", - "eslint-plugin-simple-import-sort": "7.0.0", - "eslint-plugin-sonarjs": "0.14.0", - "karma": "6.4.0", - "karma-chrome-launcher": "3.1.1", - "karma-firefox-launcher": "2.1.2", - "karma-tap": "4.2.0", - "karma-typescript": "5.5.3", - "karma-typescript-es6-transform": "5.5.3", - "lint-staged": "13.0.3", - "prettier": "2.7.1", - "sort-package-json": "1.57.0", - "tape": "5.6.0", - "ts-node": "10.9.1", - "typedoc": "0.23.10", - "typedoc-plugin-markdown": "3.13.4", - "typescript": "4.7.4" - }, - "engines": { - "node": ">=14", - "npm": ">=7" - } - }, - "eslint": { - "dev": true - }, - "node_modules/@ampproject/remapping": { - "version": "2.2.0", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@jridgewell/gen-mapping": "^0.1.0", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/code-frame": { - "version": "7.12.11", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/highlight": "^7.10.4" - } - }, - "node_modules/@babel/compat-data": { - "version": "7.19.4", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/core": { - "version": "7.19.6", - "dev": true, - "license": "MIT", - "dependencies": { - "@ampproject/remapping": "^2.1.0", - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.19.6", - "@babel/helper-compilation-targets": "^7.19.3", - "@babel/helper-module-transforms": "^7.19.6", - "@babel/helpers": "^7.19.4", - "@babel/parser": "^7.19.6", - "@babel/template": "^7.18.10", - "@babel/traverse": "^7.19.6", - "@babel/types": "^7.19.4", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.1", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@babel/core/node_modules/@babel/code-frame": { - "version": "7.18.6", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/highlight": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/core/node_modules/convert-source-map": { - "version": "1.9.0", - "dev": true, - "license": "MIT" - }, - "node_modules/@babel/core/node_modules/semver": { - "version": "6.3.0", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/generator": { - "version": "7.19.6", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.19.4", - "@jridgewell/gen-mapping": "^0.3.2", - "jsesc": "^2.5.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/generator/node_modules/@jridgewell/gen-mapping": { - "version": "0.3.2", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/helper-annotate-as-pure": { - "version": "7.18.6", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.18.9", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-explode-assignable-expression": "^7.18.6", - "@babel/types": "^7.18.9" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.19.3", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/compat-data": "^7.19.3", - "@babel/helper-validator-option": "^7.18.6", - "browserslist": "^4.21.3", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-compilation-targets/node_modules/semver": { - "version": "6.3.0", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.19.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-function-name": "^7.19.0", - "@babel/helper-member-expression-to-functions": "^7.18.9", - "@babel/helper-optimise-call-expression": "^7.18.6", - "@babel/helper-replace-supers": "^7.18.9", - "@babel/helper-split-export-declaration": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-create-regexp-features-plugin": { - "version": "7.19.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "regexpu-core": "^5.1.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.3.3", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-compilation-targets": "^7.17.7", - "@babel/helper-plugin-utils": "^7.16.7", - "debug": "^4.1.1", - "lodash.debounce": "^4.0.8", - "resolve": "^1.14.2", - "semver": "^6.1.2" - }, - "peerDependencies": { - "@babel/core": "^7.4.0-0" - } - }, - "node_modules/@babel/helper-define-polyfill-provider/node_modules/semver": { - "version": "6.3.0", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/helper-environment-visitor": { - "version": "7.18.9", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-explode-assignable-expression": { - "version": "7.18.6", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-function-name": { - "version": "7.19.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/template": "^7.18.10", - "@babel/types": "^7.19.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-hoist-variables": { - "version": "7.18.6", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.18.9", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.18.9" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-imports": { - "version": "7.18.6", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.19.6", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-simple-access": "^7.19.4", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/helper-validator-identifier": "^7.19.1", - "@babel/template": "^7.18.10", - "@babel/traverse": "^7.19.6", - "@babel/types": "^7.19.4" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-optimise-call-expression": { - "version": "7.18.6", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-plugin-utils": { - "version": "7.19.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-remap-async-to-generator": { - "version": "7.18.9", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-wrap-function": "^7.18.9", - "@babel/types": "^7.18.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-replace-supers": { - "version": "7.19.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-member-expression-to-functions": "^7.18.9", - "@babel/helper-optimise-call-expression": "^7.18.6", - "@babel/traverse": "^7.19.1", - "@babel/types": "^7.19.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-simple-access": { - "version": "7.19.4", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.19.4" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.18.9", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.18.9" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-split-export-declaration": { - "version": "7.18.6", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-string-parser": { - "version": "7.19.4", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.19.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-option": { - "version": "7.18.6", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-wrap-function": { - "version": "7.19.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-function-name": "^7.19.0", - "@babel/template": "^7.18.10", - "@babel/traverse": "^7.19.0", - "@babel/types": "^7.19.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helpers": { - "version": "7.19.4", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/template": "^7.18.10", - "@babel/traverse": "^7.19.4", - "@babel/types": "^7.19.4" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight": { - "version": "7.18.6", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-validator-identifier": "^7.18.6", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight/node_modules/ansi-styles": { - "version": "3.2.1", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/chalk": { - "version": "2.4.2", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/color-convert": { - "version": "1.9.3", - "dev": true, - "license": "MIT", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/@babel/highlight/node_modules/color-name": { - "version": "1.1.3", - "dev": true, - "license": "MIT" - }, - "node_modules/@babel/highlight/node_modules/has-flag": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/supports-color": { - "version": "5.5.0", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/parser": { - "version": "7.19.6", - "dev": true, - "license": "MIT", - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { - "version": "7.18.6", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { - "version": "7.18.9", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.9", - "@babel/helper-skip-transparent-expression-wrappers": "^7.18.9", - "@babel/plugin-proposal-optional-chaining": "^7.18.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.13.0" - } - }, - "node_modules/@babel/plugin-proposal-async-generator-functions": { - "version": "7.19.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-plugin-utils": "^7.19.0", - "@babel/helper-remap-async-to-generator": "^7.18.9", - "@babel/plugin-syntax-async-generators": "^7.8.4" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-class-properties": { - "version": "7.18.6", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-class-static-block": { - "version": "7.18.6", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-class-static-block": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.12.0" - } - }, - "node_modules/@babel/plugin-proposal-dynamic-import": { - "version": "7.18.6", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-dynamic-import": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-export-namespace-from": { - "version": "7.18.9", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.9", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-json-strings": { - "version": "7.18.6", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-json-strings": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-logical-assignment-operators": { - "version": "7.18.9", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.9", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-nullish-coalescing-operator": { - "version": "7.18.6", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-numeric-separator": { - "version": "7.18.6", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-numeric-separator": "^7.10.4" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-object-rest-spread": { - "version": "7.19.4", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/compat-data": "^7.19.4", - "@babel/helper-compilation-targets": "^7.19.3", - "@babel/helper-plugin-utils": "^7.19.0", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-transform-parameters": "^7.18.8" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-optional-catch-binding": { - "version": "7.18.6", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-optional-chaining": { - "version": "7.18.9", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.9", - "@babel/helper-skip-transparent-expression-wrappers": "^7.18.9", - "@babel/plugin-syntax-optional-chaining": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-private-methods": { - "version": "7.18.6", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-private-property-in-object": { - "version": "7.18.6", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-create-class-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-unicode-property-regex": { - "version": "7.18.6", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-async-generators": { - "version": "7.8.4", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-class-properties": { - "version": "7.12.13", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.12.13" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-class-static-block": { - "version": "7.14.5", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-dynamic-import": { - "version": "7.8.3", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-export-namespace-from": { - "version": "7.8.3", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.3" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-import-assertions": { - "version": "7.18.6", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-json-strings": { - "version": "7.8.3", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-logical-assignment-operators": { - "version": "7.10.4", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { - "version": "7.8.3", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-numeric-separator": { - "version": "7.10.4", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-object-rest-spread": { - "version": "7.8.3", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-optional-catch-binding": { - "version": "7.8.3", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-optional-chaining": { - "version": "7.8.3", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-private-property-in-object": { - "version": "7.14.5", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-top-level-await": { - "version": "7.14.5", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-arrow-functions": { - "version": "7.18.6", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-async-to-generator": { - "version": "7.18.6", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/helper-remap-async-to-generator": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-block-scoped-functions": { - "version": "7.18.6", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-block-scoping": { - "version": "7.19.4", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.19.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-classes": { - "version": "7.19.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-compilation-targets": "^7.19.0", - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-function-name": "^7.19.0", - "@babel/helper-optimise-call-expression": "^7.18.6", - "@babel/helper-plugin-utils": "^7.19.0", - "@babel/helper-replace-supers": "^7.18.9", - "@babel/helper-split-export-declaration": "^7.18.6", - "globals": "^11.1.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-classes/node_modules/globals": { - "version": "11.12.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/plugin-transform-computed-properties": { - "version": "7.18.9", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-destructuring": { - "version": "7.19.4", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.19.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-dotall-regex": { - "version": "7.18.6", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-duplicate-keys": { - "version": "7.18.9", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-exponentiation-operator": { - "version": "7.18.6", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-for-of": { - "version": "7.18.8", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-function-name": { - "version": "7.18.9", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-compilation-targets": "^7.18.9", - "@babel/helper-function-name": "^7.18.9", - "@babel/helper-plugin-utils": "^7.18.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-literals": { - "version": "7.18.9", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-member-expression-literals": { - "version": "7.18.6", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-modules-amd": { - "version": "7.19.6", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-module-transforms": "^7.19.6", - "@babel/helper-plugin-utils": "^7.19.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.19.6", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-module-transforms": "^7.19.6", - "@babel/helper-plugin-utils": "^7.19.0", - "@babel/helper-simple-access": "^7.19.4" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-modules-systemjs": { - "version": "7.19.6", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-hoist-variables": "^7.18.6", - "@babel/helper-module-transforms": "^7.19.6", - "@babel/helper-plugin-utils": "^7.19.0", - "@babel/helper-validator-identifier": "^7.19.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-modules-umd": { - "version": "7.18.6", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-module-transforms": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.19.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.19.0", - "@babel/helper-plugin-utils": "^7.19.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/plugin-transform-new-target": { - "version": "7.18.6", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-object-super": { - "version": "7.18.6", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/helper-replace-supers": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-parameters": { - "version": "7.18.8", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-property-literals": { - "version": "7.18.6", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-regenerator": { - "version": "7.18.6", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "regenerator-transform": "^0.15.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-reserved-words": { - "version": "7.18.6", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-shorthand-properties": { - "version": "7.18.6", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-spread": { - "version": "7.19.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.19.0", - "@babel/helper-skip-transparent-expression-wrappers": "^7.18.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-sticky-regex": { - "version": "7.18.6", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-template-literals": { - "version": "7.18.9", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-typeof-symbol": { - "version": "7.18.9", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-unicode-escapes": { - "version": "7.18.10", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-unicode-regex": { - "version": "7.18.6", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/preset-env": { - "version": "7.19.4", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/compat-data": "^7.19.4", - "@babel/helper-compilation-targets": "^7.19.3", - "@babel/helper-plugin-utils": "^7.19.0", - "@babel/helper-validator-option": "^7.18.6", - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.18.6", - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.18.9", - "@babel/plugin-proposal-async-generator-functions": "^7.19.1", - "@babel/plugin-proposal-class-properties": "^7.18.6", - "@babel/plugin-proposal-class-static-block": "^7.18.6", - "@babel/plugin-proposal-dynamic-import": "^7.18.6", - "@babel/plugin-proposal-export-namespace-from": "^7.18.9", - "@babel/plugin-proposal-json-strings": "^7.18.6", - "@babel/plugin-proposal-logical-assignment-operators": "^7.18.9", - "@babel/plugin-proposal-nullish-coalescing-operator": "^7.18.6", - "@babel/plugin-proposal-numeric-separator": "^7.18.6", - "@babel/plugin-proposal-object-rest-spread": "^7.19.4", - "@babel/plugin-proposal-optional-catch-binding": "^7.18.6", - "@babel/plugin-proposal-optional-chaining": "^7.18.9", - "@babel/plugin-proposal-private-methods": "^7.18.6", - "@babel/plugin-proposal-private-property-in-object": "^7.18.6", - "@babel/plugin-proposal-unicode-property-regex": "^7.18.6", - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-class-properties": "^7.12.13", - "@babel/plugin-syntax-class-static-block": "^7.14.5", - "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3", - "@babel/plugin-syntax-import-assertions": "^7.18.6", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.10.4", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5", - "@babel/plugin-syntax-top-level-await": "^7.14.5", - "@babel/plugin-transform-arrow-functions": "^7.18.6", - "@babel/plugin-transform-async-to-generator": "^7.18.6", - "@babel/plugin-transform-block-scoped-functions": "^7.18.6", - "@babel/plugin-transform-block-scoping": "^7.19.4", - "@babel/plugin-transform-classes": "^7.19.0", - "@babel/plugin-transform-computed-properties": "^7.18.9", - "@babel/plugin-transform-destructuring": "^7.19.4", - "@babel/plugin-transform-dotall-regex": "^7.18.6", - "@babel/plugin-transform-duplicate-keys": "^7.18.9", - "@babel/plugin-transform-exponentiation-operator": "^7.18.6", - "@babel/plugin-transform-for-of": "^7.18.8", - "@babel/plugin-transform-function-name": "^7.18.9", - "@babel/plugin-transform-literals": "^7.18.9", - "@babel/plugin-transform-member-expression-literals": "^7.18.6", - "@babel/plugin-transform-modules-amd": "^7.18.6", - "@babel/plugin-transform-modules-commonjs": "^7.18.6", - "@babel/plugin-transform-modules-systemjs": "^7.19.0", - "@babel/plugin-transform-modules-umd": "^7.18.6", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.19.1", - "@babel/plugin-transform-new-target": "^7.18.6", - "@babel/plugin-transform-object-super": "^7.18.6", - "@babel/plugin-transform-parameters": "^7.18.8", - "@babel/plugin-transform-property-literals": "^7.18.6", - "@babel/plugin-transform-regenerator": "^7.18.6", - "@babel/plugin-transform-reserved-words": "^7.18.6", - "@babel/plugin-transform-shorthand-properties": "^7.18.6", - "@babel/plugin-transform-spread": "^7.19.0", - "@babel/plugin-transform-sticky-regex": "^7.18.6", - "@babel/plugin-transform-template-literals": "^7.18.9", - "@babel/plugin-transform-typeof-symbol": "^7.18.9", - "@babel/plugin-transform-unicode-escapes": "^7.18.10", - "@babel/plugin-transform-unicode-regex": "^7.18.6", - "@babel/preset-modules": "^0.1.5", - "@babel/types": "^7.19.4", - "babel-plugin-polyfill-corejs2": "^0.3.3", - "babel-plugin-polyfill-corejs3": "^0.6.0", - "babel-plugin-polyfill-regenerator": "^0.4.1", - "core-js-compat": "^3.25.1", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/preset-env/node_modules/semver": { - "version": "6.3.0", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/preset-modules": { - "version": "0.1.5", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", - "@babel/plugin-transform-dotall-regex": "^7.4.4", - "@babel/types": "^7.4.4", - "esutils": "^2.0.2" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/runtime": { - "version": "7.19.4", - "dev": true, - "license": "MIT", - "dependencies": { - "regenerator-runtime": "^0.13.4" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/runtime-corejs3": { - "version": "7.19.6", - "dev": true, - "license": "MIT", - "dependencies": { - "core-js-pure": "^3.25.1", - "regenerator-runtime": "^0.13.4" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/template": { - "version": "7.18.10", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.18.6", - "@babel/parser": "^7.18.10", - "@babel/types": "^7.18.10" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/template/node_modules/@babel/code-frame": { - "version": "7.18.6", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/highlight": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse": { - "version": "7.19.6", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.19.6", - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-function-name": "^7.19.0", - "@babel/helper-hoist-variables": "^7.18.6", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/parser": "^7.19.6", - "@babel/types": "^7.19.4", - "debug": "^4.1.0", - "globals": "^11.1.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse/node_modules/@babel/code-frame": { - "version": "7.18.6", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/highlight": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse/node_modules/globals": { - "version": "11.12.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/types": { - "version": "7.19.4", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-string-parser": "^7.19.4", - "@babel/helper-validator-identifier": "^7.19.1", - "to-fast-properties": "^2.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@bcoe/v8-coverage": { - "version": "0.2.3", - "dev": true, - "license": "MIT" - }, - "node_modules/@chainsafe/as-sha256": { - "version": "0.4.0", - "license": "Apache-2.0" - }, - "node_modules/@chainsafe/libp2p-noise": { - "version": "4.1.2", - "license": "MIT", - "dependencies": { - "@stablelib/chacha20poly1305": "^1.0.1", - "@stablelib/hkdf": "^1.0.1", - "@stablelib/sha256": "^1.0.1", - "@stablelib/x25519": "^1.0.1", - "debug": "^4.3.1", - "it-buffer": "^0.1.3", - "it-length-prefixed": "^5.0.3", - "it-pair": "^1.0.0", - "it-pb-rpc": "^0.1.11", - "it-pipe": "^1.1.0", - "libp2p-crypto": "^0.19.7", - "peer-id": "^0.15.3", - "protobufjs": "^6.11.2", - "uint8arrays": "^3.0.0" - } - }, - "node_modules/@chainsafe/libp2p-noise/node_modules/err-code": { - "version": "3.0.1", - "license": "MIT" - }, - "node_modules/@chainsafe/libp2p-noise/node_modules/peer-id": { - "version": "0.15.4", - "license": "MIT", - "dependencies": { - "class-is": "^1.1.0", - "libp2p-crypto": "^0.20.0", - "minimist": "^1.2.5", - "multiformats": "^9.4.5", - "protobufjs": "^6.10.2", - "uint8arrays": "^3.0.0" - }, - "bin": { - "peer-id": "src/bin.js" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@chainsafe/libp2p-noise/node_modules/peer-id/node_modules/libp2p-crypto": { - "version": "0.20.0", - "license": "MIT", - "dependencies": { - "err-code": "^3.0.1", - "iso-random-stream": "^2.0.0", - "keypair": "^1.0.4", - "multiformats": "^9.4.5", - "noble-ed25519": "^1.2.6", - "noble-secp256k1": "^1.2.10", - "node-forge": "^0.10.0", - "pem-jwk": "^2.0.0", - "protobufjs": "^6.11.2", - "uint8arrays": "^3.0.0", - "ursa-optional": "^0.10.1" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@chainsafe/persistent-merkle-tree": { - "version": "0.6.0", - "license": "Apache-2.0", - "dependencies": { - "@chainsafe/as-sha256": "^0.4.0", - "@noble/hashes": "^1.3.0" - } - }, - "node_modules/@chainsafe/ssz": { - "version": "0.11.0", - "license": "Apache-2.0", - "dependencies": { - "@chainsafe/as-sha256": "^0.4.0", - "@chainsafe/persistent-merkle-tree": "^0.6.0" - } - }, - "node_modules/@colors/colors": { - "version": "1.5.0", - "license": "MIT", - "engines": { - "node": ">=0.1.90" - } - }, - "node_modules/@cspotcode/source-map-support": { - "version": "0.8.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/trace-mapping": "0.3.9" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { - "version": "0.3.9", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" - } - }, - "node_modules/@dabh/diagnostics": { - "version": "2.0.3", - "license": "MIT", - "dependencies": { - "colorspace": "1.1.x", - "enabled": "2.0.x", - "kuler": "^2.0.0" - } - }, - "node_modules/@discoveryjs/json-ext": { - "version": "0.5.7", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/@eslint/eslintrc": { - "version": "1.3.3", - "dev": true, - "license": "MIT", - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.4.0", - "globals": "^13.15.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@ethereumjs/block": { - "resolved": "packages/block", - "link": true - }, - "node_modules/@ethereumjs/blockchain": { - "resolved": "packages/blockchain", - "link": true - }, - "node_modules/@ethereumjs/client": { - "resolved": "packages/client", - "link": true - }, - "node_modules/@ethereumjs/common": { - "resolved": "packages/common", - "link": true - }, - "node_modules/@ethereumjs/devp2p": { - "resolved": "packages/devp2p", - "link": true - }, - "node_modules/@ethereumjs/ethash": { - "resolved": "packages/ethash", - "link": true - }, - "node_modules/@ethereumjs/evm": { - "resolved": "packages/evm", - "link": true - }, - "node_modules/@ethereumjs/rlp": { - "resolved": "packages/rlp", - "link": true - }, - "node_modules/@ethereumjs/statemanager": { - "resolved": "packages/statemanager", - "link": true - }, - "node_modules/@ethereumjs/trie": { - "resolved": "packages/trie", - "link": true - }, - "node_modules/@ethereumjs/tx": { - "resolved": "packages/tx", - "link": true - }, - "node_modules/@ethereumjs/util": { - "resolved": "packages/util", - "link": true - }, - "node_modules/@ethereumjs/vm": { - "resolved": "packages/vm", - "link": true - }, - "node_modules/@ethersproject/abi": { - "version": "5.7.0", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "dependencies": { - "@ethersproject/address": "^5.7.0", - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/constants": "^5.7.0", - "@ethersproject/hash": "^5.7.0", - "@ethersproject/keccak256": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/strings": "^5.7.0" - } - }, - "node_modules/@ethersproject/abstract-provider": { - "version": "5.7.0", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "dependencies": { - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/networks": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/transactions": "^5.7.0", - "@ethersproject/web": "^5.7.0" - } - }, - "node_modules/@ethersproject/abstract-signer": { - "version": "5.7.0", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "dependencies": { - "@ethersproject/abstract-provider": "^5.7.0", - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0" - } - }, - "node_modules/@ethersproject/address": { - "version": "5.7.0", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "dependencies": { - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/keccak256": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/rlp": "^5.7.0" - } - }, - "node_modules/@ethersproject/base64": { - "version": "5.7.0", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "dependencies": { - "@ethersproject/bytes": "^5.7.0" - } - }, - "node_modules/@ethersproject/basex": { - "version": "5.7.0", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/properties": "^5.7.0" - } - }, - "node_modules/@ethersproject/bignumber": { - "version": "5.7.0", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "bn.js": "^5.2.1" - } - }, - "node_modules/@ethersproject/bytes": { - "version": "5.7.0", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "dependencies": { - "@ethersproject/logger": "^5.7.0" - } - }, - "node_modules/@ethersproject/constants": { - "version": "5.7.0", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "dependencies": { - "@ethersproject/bignumber": "^5.7.0" - } - }, - "node_modules/@ethersproject/contracts": { - "version": "5.7.0", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "dependencies": { - "@ethersproject/abi": "^5.7.0", - "@ethersproject/abstract-provider": "^5.7.0", - "@ethersproject/abstract-signer": "^5.7.0", - "@ethersproject/address": "^5.7.0", - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/constants": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/transactions": "^5.7.0" - } - }, - "node_modules/@ethersproject/hash": { - "version": "5.7.0", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "dependencies": { - "@ethersproject/abstract-signer": "^5.7.0", - "@ethersproject/address": "^5.7.0", - "@ethersproject/base64": "^5.7.0", - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/keccak256": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/strings": "^5.7.0" - } - }, - "node_modules/@ethersproject/hdnode": { - "version": "5.7.0", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "dependencies": { - "@ethersproject/abstract-signer": "^5.7.0", - "@ethersproject/basex": "^5.7.0", - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/pbkdf2": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/sha2": "^5.7.0", - "@ethersproject/signing-key": "^5.7.0", - "@ethersproject/strings": "^5.7.0", - "@ethersproject/transactions": "^5.7.0", - "@ethersproject/wordlists": "^5.7.0" - } - }, - "node_modules/@ethersproject/json-wallets": { - "version": "5.7.0", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "dependencies": { - "@ethersproject/abstract-signer": "^5.7.0", - "@ethersproject/address": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/hdnode": "^5.7.0", - "@ethersproject/keccak256": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/pbkdf2": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/random": "^5.7.0", - "@ethersproject/strings": "^5.7.0", - "@ethersproject/transactions": "^5.7.0", - "aes-js": "3.0.0", - "scrypt-js": "3.0.1" - } - }, - "node_modules/@ethersproject/keccak256": { - "version": "5.7.0", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "js-sha3": "0.8.0" - } - }, - "node_modules/@ethersproject/logger": { - "version": "5.7.0", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT" - }, - "node_modules/@ethersproject/networks": { - "version": "5.7.1", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "dependencies": { - "@ethersproject/logger": "^5.7.0" - } - }, - "node_modules/@ethersproject/pbkdf2": { - "version": "5.7.0", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/sha2": "^5.7.0" - } - }, - "node_modules/@ethersproject/properties": { - "version": "5.7.0", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "dependencies": { - "@ethersproject/logger": "^5.7.0" - } - }, - "node_modules/@ethersproject/providers": { - "version": "5.7.2", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "dependencies": { - "@ethersproject/abstract-provider": "^5.7.0", - "@ethersproject/abstract-signer": "^5.7.0", - "@ethersproject/address": "^5.7.0", - "@ethersproject/base64": "^5.7.0", - "@ethersproject/basex": "^5.7.0", - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/constants": "^5.7.0", - "@ethersproject/hash": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/networks": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/random": "^5.7.0", - "@ethersproject/rlp": "^5.7.0", - "@ethersproject/sha2": "^5.7.0", - "@ethersproject/strings": "^5.7.0", - "@ethersproject/transactions": "^5.7.0", - "@ethersproject/web": "^5.7.0", - "bech32": "1.1.4", - "ws": "7.4.6" - } - }, - "node_modules/@ethersproject/providers/node_modules/ws": { - "version": "7.4.6", - "license": "MIT", - "engines": { - "node": ">=8.3.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/@ethersproject/random": { - "version": "5.7.0", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0" - } - }, - "node_modules/@ethersproject/rlp": { - "version": "5.7.0", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0" - } - }, - "node_modules/@ethersproject/sha2": { - "version": "5.7.0", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "hash.js": "1.1.7" - } - }, - "node_modules/@ethersproject/signing-key": { - "version": "5.7.0", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "bn.js": "^5.2.1", - "elliptic": "6.5.4", - "hash.js": "1.1.7" - } - }, - "node_modules/@ethersproject/solidity": { - "version": "5.7.0", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "dependencies": { - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/keccak256": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/sha2": "^5.7.0", - "@ethersproject/strings": "^5.7.0" - } - }, - "node_modules/@ethersproject/strings": { - "version": "5.7.0", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/constants": "^5.7.0", - "@ethersproject/logger": "^5.7.0" - } - }, - "node_modules/@ethersproject/transactions": { - "version": "5.7.0", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "dependencies": { - "@ethersproject/address": "^5.7.0", - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/constants": "^5.7.0", - "@ethersproject/keccak256": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/rlp": "^5.7.0", - "@ethersproject/signing-key": "^5.7.0" - } - }, - "node_modules/@ethersproject/units": { - "version": "5.7.0", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "dependencies": { - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/constants": "^5.7.0", - "@ethersproject/logger": "^5.7.0" - } - }, - "node_modules/@ethersproject/wallet": { - "version": "5.7.0", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "dependencies": { - "@ethersproject/abstract-provider": "^5.7.0", - "@ethersproject/abstract-signer": "^5.7.0", - "@ethersproject/address": "^5.7.0", - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/hash": "^5.7.0", - "@ethersproject/hdnode": "^5.7.0", - "@ethersproject/json-wallets": "^5.7.0", - "@ethersproject/keccak256": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/random": "^5.7.0", - "@ethersproject/signing-key": "^5.7.0", - "@ethersproject/transactions": "^5.7.0", - "@ethersproject/wordlists": "^5.7.0" - } - }, - "node_modules/@ethersproject/web": { - "version": "5.7.1", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "dependencies": { - "@ethersproject/base64": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/strings": "^5.7.0" - } - }, - "node_modules/@ethersproject/wordlists": { - "version": "5.7.0", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/hash": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/strings": "^5.7.0" - } - }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.10.7", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@humanwhocodes/object-schema": "^1.2.1", - "debug": "^4.1.1", - "minimatch": "^3.0.4" - }, - "engines": { - "node": ">=10.10.0" - } - }, - "node_modules/@humanwhocodes/gitignore-to-minimatch": { - "version": "1.0.2", - "dev": true, - "license": "Apache-2.0", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@humanwhocodes/object-schema": { - "version": "1.2.1", - "dev": true, - "license": "BSD-3-Clause" - }, - "node_modules/@istanbuljs/load-nyc-config": { - "version": "1.1.0", - "dev": true, - "license": "ISC", - "dependencies": { - "camelcase": "^5.3.1", - "find-up": "^4.1.0", - "get-package-type": "^0.1.0", - "js-yaml": "^3.13.1", - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": { - "version": "1.0.10", - "dev": true, - "license": "MIT", - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { - "version": "4.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { - "version": "3.14.1", - "dev": true, - "license": "MIT", - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { - "version": "5.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": { - "version": "2.3.0", - "dev": true, - "license": "MIT", - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { - "version": "4.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": { - "version": "5.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/sprintf-js": { - "version": "1.0.3", - "dev": true, - "license": "BSD-3-Clause" - }, - "node_modules/@istanbuljs/schema": { - "version": "0.1.3", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.1.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/set-array": "^1.0.0", - "@jridgewell/sourcemap-codec": "^1.4.10" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/source-map": { - "version": "0.3.2", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" - } - }, - "node_modules/@jridgewell/source-map/node_modules/@jridgewell/gen-mapping": { - "version": "0.3.2", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "dev": true, - "license": "MIT" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.17", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "3.1.0", - "@jridgewell/sourcemap-codec": "1.4.14" - } - }, - "node_modules/@motrix/nat-api": { - "version": "0.3.2", - "license": "MIT", - "dependencies": { - "async": "^3.2.0", - "debug": "^4.3.1", - "default-gateway": "^6.0.3", - "request": "^2.88.2", - "unordered-array-remove": "^1.0.2", - "xml2js": "^0.4.23" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/@multiformats/base-x": { - "version": "4.0.1", - "license": "MIT" - }, - "node_modules/@noble/curves": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.0.0.tgz", - "integrity": "sha512-2upgEu0iLiDVDZkNLeFV2+ht0BAVgQnEmCk6JsOch9Rp8xfkMCbvbAZlA2pBHQc73dbl+vFOXfqkf4uemdn0bw==", - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], - "dependencies": { - "@noble/hashes": "1.3.0" - } - }, - "node_modules/@noble/ed25519": { - "version": "1.7.1", - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], - "license": "MIT" - }, - "node_modules/@noble/hashes": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.0.tgz", - "integrity": "sha512-ilHEACi9DwqJB0pw7kv+Apvh50jiiSyR/cQ3y4W7lOR5mhvn/50FLUfsnfJz0BDZtl/RR16kXvptiv6q1msYZg==", - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ] - }, - "node_modules/@noble/secp256k1": { - "version": "1.6.3", - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], - "license": "MIT" - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@protobufjs/aspromise": { - "version": "1.1.2", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/base64": { - "version": "1.1.2", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/codegen": { - "version": "2.0.4", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/eventemitter": { - "version": "1.1.0", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/fetch": { - "version": "1.1.0", - "license": "BSD-3-Clause", - "dependencies": { - "@protobufjs/aspromise": "^1.1.1", - "@protobufjs/inquire": "^1.1.0" - } - }, - "node_modules/@protobufjs/float": { - "version": "1.0.2", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/inquire": { - "version": "1.1.0", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/path": { - "version": "1.1.2", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/pool": { - "version": "1.1.0", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/utf8": { - "version": "1.1.0", - "license": "BSD-3-Clause" - }, - "node_modules/@scure/base": { - "version": "1.1.1", - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], - "license": "MIT" - }, - "node_modules/@scure/bip32": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.3.0.tgz", - "integrity": "sha512-bcKpo1oj54hGholplGLpqPHRbIsnbixFtc06nwuNM5/dwSXOq/AAYoIBRsBmnZJSdfeNW5rnff7NTAz3ZCqR9Q==", - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], - "dependencies": { - "@noble/curves": "~1.0.0", - "@noble/hashes": "~1.3.0", - "@scure/base": "~1.1.0" - } - }, - "node_modules/@scure/bip39": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.2.0.tgz", - "integrity": "sha512-SX/uKq52cuxm4YFXWFaVByaSHJh2w3BnokVSeUJVCv6K7WulT9u2BuNRBhuFl8vAuYnzx9bEu9WgpcNYTrYieg==", - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], - "dependencies": { - "@noble/hashes": "~1.3.0", - "@scure/base": "~1.1.0" - } - }, - "node_modules/@sinonjs/commons": { - "version": "1.8.3", - "license": "BSD-3-Clause", - "dependencies": { - "type-detect": "4.0.8" - } - }, - "node_modules/@sinonjs/fake-timers": { - "version": "6.0.1", - "license": "BSD-3-Clause", - "dependencies": { - "@sinonjs/commons": "^1.7.0" - } - }, - "node_modules/@sinonjs/samsam": { - "version": "5.3.1", - "license": "BSD-3-Clause", - "dependencies": { - "@sinonjs/commons": "^1.6.0", - "lodash.get": "^4.4.2", - "type-detect": "^4.0.8" - } - }, - "node_modules/@sinonjs/text-encoding": { - "version": "0.7.2", - "license": "(Unlicense OR Apache-2.0)" - }, - "node_modules/@socket.io/component-emitter": { - "version": "3.1.0", - "dev": true, - "license": "MIT" - }, - "node_modules/@stablelib/aead": { - "version": "1.0.1", - "license": "MIT" - }, - "node_modules/@stablelib/binary": { - "version": "1.0.1", - "license": "MIT", - "dependencies": { - "@stablelib/int": "^1.0.1" - } - }, - "node_modules/@stablelib/bytes": { - "version": "1.0.1", - "license": "MIT" - }, - "node_modules/@stablelib/chacha": { - "version": "1.0.1", - "license": "MIT", - "dependencies": { - "@stablelib/binary": "^1.0.1", - "@stablelib/wipe": "^1.0.1" - } - }, - "node_modules/@stablelib/chacha20poly1305": { - "version": "1.0.1", - "license": "MIT", - "dependencies": { - "@stablelib/aead": "^1.0.1", - "@stablelib/binary": "^1.0.1", - "@stablelib/chacha": "^1.0.1", - "@stablelib/constant-time": "^1.0.1", - "@stablelib/poly1305": "^1.0.1", - "@stablelib/wipe": "^1.0.1" - } - }, - "node_modules/@stablelib/constant-time": { - "version": "1.0.1", - "license": "MIT" - }, - "node_modules/@stablelib/hash": { - "version": "1.0.1", - "license": "MIT" - }, - "node_modules/@stablelib/hkdf": { - "version": "1.0.1", - "license": "MIT", - "dependencies": { - "@stablelib/hash": "^1.0.1", - "@stablelib/hmac": "^1.0.1", - "@stablelib/wipe": "^1.0.1" - } - }, - "node_modules/@stablelib/hmac": { - "version": "1.0.1", - "license": "MIT", - "dependencies": { - "@stablelib/constant-time": "^1.0.1", - "@stablelib/hash": "^1.0.1", - "@stablelib/wipe": "^1.0.1" - } - }, - "node_modules/@stablelib/int": { - "version": "1.0.1", - "license": "MIT" - }, - "node_modules/@stablelib/keyagreement": { - "version": "1.0.1", - "license": "MIT", - "dependencies": { - "@stablelib/bytes": "^1.0.1" - } - }, - "node_modules/@stablelib/poly1305": { - "version": "1.0.1", - "license": "MIT", - "dependencies": { - "@stablelib/constant-time": "^1.0.1", - "@stablelib/wipe": "^1.0.1" - } - }, - "node_modules/@stablelib/random": { - "version": "1.0.2", - "license": "MIT", - "dependencies": { - "@stablelib/binary": "^1.0.1", - "@stablelib/wipe": "^1.0.1" - } - }, - "node_modules/@stablelib/sha256": { - "version": "1.0.1", - "license": "MIT", - "dependencies": { - "@stablelib/binary": "^1.0.1", - "@stablelib/hash": "^1.0.1", - "@stablelib/wipe": "^1.0.1" - } - }, - "node_modules/@stablelib/wipe": { - "version": "1.0.1", - "license": "MIT" - }, - "node_modules/@stablelib/x25519": { - "version": "1.0.3", - "license": "MIT", - "dependencies": { - "@stablelib/keyagreement": "^1.0.1", - "@stablelib/random": "^1.0.2", - "@stablelib/wipe": "^1.0.1" - } - }, - "node_modules/@tsconfig/node10": { - "version": "1.0.9", - "dev": true, - "license": "MIT" - }, - "node_modules/@tsconfig/node12": { - "version": "1.0.11", - "dev": true, - "license": "MIT" - }, - "node_modules/@tsconfig/node14": { - "version": "1.0.3", - "dev": true, - "license": "MIT" - }, - "node_modules/@tsconfig/node16": { - "version": "1.0.3", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/async": { - "version": "2.4.2", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/benchmark": { - "version": "1.0.33", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/bl": { - "version": "2.1.0", - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/bn.js": { - "version": "5.1.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/body-parser": { - "version": "1.19.2", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/connect": "*", - "@types/node": "*" - } - }, - "node_modules/@types/chalk": { - "version": "2.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "*" - } - }, - "node_modules/@types/connect": { - "version": "3.4.35", - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/cookie": { - "version": "0.4.1", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/cookiejar": { - "version": "2.1.2", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/core-js": { - "version": "2.5.5", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/cors": { - "version": "2.8.12", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/debug": { - "version": "4.1.7", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/ms": "*" - } - }, - "node_modules/@types/eslint": { - "version": "8.4.7", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "*", - "@types/json-schema": "*" - } - }, - "node_modules/@types/eslint-scope": { - "version": "3.7.4", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/eslint": "*", - "@types/estree": "*" - } - }, - "node_modules/@types/estree": { - "version": "0.0.51", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/fs-extra": { - "version": "9.0.13", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/glob": { - "version": "7.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/minimatch": "*", - "@types/node": "*" - } - }, - "node_modules/@types/ip": { - "version": "1.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/istanbul-lib-coverage": { - "version": "2.0.4", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/json-schema": { - "version": "7.0.11", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/json5": { - "version": "0.0.29", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/jwt-simple": { - "version": "0.5.33", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/k-bucket": { - "version": "5.0.1", - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/level-errors": { - "version": "3.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/long": { - "version": "4.0.2", - "license": "MIT" - }, - "node_modules/@types/minimatch": { - "version": "3.0.5", - "license": "MIT" - }, - "node_modules/@types/minimist": { - "version": "1.2.2", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/ms": { - "version": "0.7.31", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/node": { - "version": "16.11.49", - "license": "MIT" - }, - "node_modules/@types/node-dir": { - "version": "0.0.34", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/readable-stream": { - "version": "2.3.14", - "license": "MIT", - "dependencies": { - "@types/node": "*", - "safe-buffer": "*" - } - }, - "node_modules/@types/retry": { - "version": "0.12.0", - "license": "MIT" - }, - "node_modules/@types/secp256k1": { - "version": "4.0.3", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/superagent": { - "version": "4.1.15", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/cookiejar": "*", - "@types/node": "*" - } - }, - "node_modules/@types/supertest": { - "version": "2.0.12", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/superagent": "*" - } - }, - "node_modules/@types/tape": { - "version": "4.13.2", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/ws": { - "version": "7.4.7", - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/yargs": { - "version": "17.0.24", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/yargs-parser": "*" - } - }, - "node_modules/@types/yargs-parser": { - "version": "21.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.33.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/scope-manager": "5.33.1", - "@typescript-eslint/type-utils": "5.33.1", - "@typescript-eslint/utils": "5.33.1", - "debug": "^4.3.4", - "functional-red-black-tree": "^1.0.1", - "ignore": "^5.2.0", - "regexpp": "^3.2.0", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^5.0.0", - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/parser": { - "version": "5.33.1", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "@typescript-eslint/scope-manager": "5.33.1", - "@typescript-eslint/types": "5.33.1", - "@typescript-eslint/typescript-estree": "5.33.1", - "debug": "^4.3.4" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "5.33.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "5.33.1", - "@typescript-eslint/visitor-keys": "5.33.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/type-utils": { - "version": "5.33.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/utils": "5.33.1", - "debug": "^4.3.4", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "*" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/types": { - "version": "5.33.1", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.33.1", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "@typescript-eslint/types": "5.33.1", - "@typescript-eslint/visitor-keys": "5.33.1", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/utils": { - "version": "5.33.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/json-schema": "^7.0.9", - "@typescript-eslint/scope-manager": "5.33.1", - "@typescript-eslint/types": "5.33.1", - "@typescript-eslint/typescript-estree": "5.33.1", - "eslint-scope": "^5.1.1", - "eslint-utils": "^3.0.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.33.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "5.33.1", - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@webassemblyjs/ast": { - "version": "1.11.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@webassemblyjs/helper-numbers": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1" - } - }, - "node_modules/@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.1", - "dev": true, - "license": "MIT" - }, - "node_modules/@webassemblyjs/helper-api-error": { - "version": "1.11.1", - "dev": true, - "license": "MIT" - }, - "node_modules/@webassemblyjs/helper-buffer": { - "version": "1.11.1", - "dev": true, - "license": "MIT" - }, - "node_modules/@webassemblyjs/helper-numbers": { - "version": "1.11.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@webassemblyjs/floating-point-hex-parser": "1.11.1", - "@webassemblyjs/helper-api-error": "1.11.1", - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.1", - "dev": true, - "license": "MIT" - }, - "node_modules/@webassemblyjs/helper-wasm-section": { - "version": "1.11.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1" - } - }, - "node_modules/@webassemblyjs/ieee754": { - "version": "1.11.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@xtuc/ieee754": "^1.2.0" - } - }, - "node_modules/@webassemblyjs/leb128": { - "version": "1.11.1", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@webassemblyjs/utf8": { - "version": "1.11.1", - "dev": true, - "license": "MIT" - }, - "node_modules/@webassemblyjs/wasm-edit": { - "version": "1.11.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/helper-wasm-section": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1", - "@webassemblyjs/wasm-opt": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1", - "@webassemblyjs/wast-printer": "1.11.1" - } - }, - "node_modules/@webassemblyjs/wasm-gen": { - "version": "1.11.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/ieee754": "1.11.1", - "@webassemblyjs/leb128": "1.11.1", - "@webassemblyjs/utf8": "1.11.1" - } - }, - "node_modules/@webassemblyjs/wasm-opt": { - "version": "1.11.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1" - } - }, - "node_modules/@webassemblyjs/wasm-parser": { - "version": "1.11.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-api-error": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/ieee754": "1.11.1", - "@webassemblyjs/leb128": "1.11.1", - "@webassemblyjs/utf8": "1.11.1" - } - }, - "node_modules/@webassemblyjs/wast-printer": { - "version": "1.11.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@webpack-cli/configtest": { - "version": "1.2.0", - "dev": true, - "license": "MIT", - "peerDependencies": { - "webpack": "4.x.x || 5.x.x", - "webpack-cli": "4.x.x" - } - }, - "node_modules/@webpack-cli/info": { - "version": "1.5.0", - "dev": true, - "license": "MIT", - "dependencies": { - "envinfo": "^7.7.3" - }, - "peerDependencies": { - "webpack-cli": "4.x.x" - } - }, - "node_modules/@webpack-cli/serve": { - "version": "1.7.0", - "dev": true, - "license": "MIT", - "peerDependencies": { - "webpack-cli": "4.x.x" - }, - "peerDependenciesMeta": { - "webpack-dev-server": { - "optional": true - } - } - }, - "node_modules/@xtuc/ieee754": { - "version": "1.2.0", - "dev": true, - "license": "BSD-3-Clause" - }, - "node_modules/@xtuc/long": { - "version": "4.2.2", - "dev": true, - "license": "Apache-2.0" - }, - "node_modules/@zxing/text-encoding": { - "version": "0.9.0", - "license": "(Unlicense OR Apache-2.0)", - "optional": true - }, - "node_modules/0x": { - "version": "4.11.0", - "dev": true, - "license": "MIT", - "dependencies": { - "ajv": "^6.9.2", - "browserify": "^16.2.3", - "concat-stream": "^1.5.2", - "d3-fg": "^6.14.0", - "debounce": "^1.2.0", - "debug": "^4.1.1", - "end-of-stream": "^1.1.0", - "env-string": "^1.0.0", - "escape-string-regexp": "^1.0.5", - "execspawn": "^1.0.1", - "has-unicode": "^2.0.1", - "hsl-to-rgb-for-reals": "^1.1.0", - "jsonstream2": "^1.1.2", - "make-dir": "^1.3.0", - "minimist": "^1.2.0", - "morphdom": "^2.3.3", - "nanohtml": "^1.4.0", - "on-net-listen": "^1.1.0", - "opn": "^5.4.0", - "perf-sym": "^2.0.3", - "pump": "^3.0.0", - "pumpify": "^1.4.0", - "semver": "^5.5.1", - "single-line-log": "^1.0.1", - "split2": "^3.1.0", - "tachyons": "^4.9.1", - "through2": "^2.0.5", - "which": "^1.2.4" - }, - "bin": { - "0x": "cmd.js" - }, - "engines": { - "node": ">=8.5.0" - } - }, - "node_modules/0x/node_modules/semver": { - "version": "5.7.1", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/abort-controller": { - "version": "3.0.0", - "license": "MIT", - "dependencies": { - "event-target-shim": "^5.0.0" - }, - "engines": { - "node": ">=6.5" - } - }, - "node_modules/abortable-iterator": { - "version": "3.0.2", - "license": "MIT", - "dependencies": { - "get-iterator": "^1.0.2" - } - }, - "node_modules/abstract-level": { - "version": "1.0.3", - "license": "MIT", - "dependencies": { - "buffer": "^6.0.3", - "catering": "^2.1.0", - "is-buffer": "^2.0.5", - "level-supports": "^4.0.0", - "level-transcoder": "^1.0.1", - "module-error": "^1.0.1", - "queue-microtask": "^1.2.3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/abstract-leveldown": { - "version": "7.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "buffer": "^6.0.3", - "catering": "^2.0.0", - "is-buffer": "^2.0.5", - "level-concat-iterator": "^3.0.0", - "level-supports": "^2.0.1", - "queue-microtask": "^1.2.3" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/abstract-leveldown/node_modules/level-supports": { - "version": "2.1.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - } - }, - "node_modules/accepts": { - "version": "1.3.8", - "dev": true, - "license": "MIT", - "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/acorn": { - "version": "8.8.0", - "dev": true, - "license": "MIT", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-import-assertions": { - "version": "1.8.0", - "dev": true, - "license": "MIT", - "peerDependencies": { - "acorn": "^8" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "dev": true, - "license": "MIT", - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/acorn-node": { - "version": "1.8.2", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "acorn": "^7.0.0", - "acorn-walk": "^7.0.0", - "xtend": "^4.0.2" - } - }, - "node_modules/acorn-node/node_modules/acorn": { - "version": "7.4.1", - "dev": true, - "license": "MIT", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-walk": { - "version": "7.2.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/aes-js": { - "version": "3.0.0", - "license": "MIT" - }, - "node_modules/aggregate-error": { - "version": "3.1.0", - "license": "MIT", - "dependencies": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/ajv": { - "version": "6.12.6", - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ajv-keywords": { - "version": "3.5.2", - "dev": true, - "license": "MIT", - "peerDependencies": { - "ajv": "^6.9.1" - } - }, - "node_modules/ansi-escapes": { - "version": "4.3.2", - "dev": true, - "license": "MIT", - "dependencies": { - "type-fest": "^0.21.3" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ansi-escapes/node_modules/type-fest": { - "version": "0.21.3", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/ansicolors": { - "version": "0.2.1", - "dev": true, - "license": "MIT" - }, - "node_modules/any-signal": { - "version": "2.1.2", - "license": "MIT", - "dependencies": { - "abort-controller": "^3.0.0", - "native-abort-controller": "^1.0.3" - } - }, - "node_modules/anymatch": { - "version": "3.1.2", - "dev": true, - "license": "ISC", - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/append-transform": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "default-require-extensions": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/archy": { - "version": "1.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/arg": { - "version": "4.1.3", - "dev": true, - "license": "MIT" - }, - "node_modules/argparse": { - "version": "2.0.1", - "dev": true, - "license": "Python-2.0" - }, - "node_modules/aria-query": { - "version": "4.2.2", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@babel/runtime": "^7.10.2", - "@babel/runtime-corejs3": "^7.10.2" - }, - "engines": { - "node": ">=6.0" - } - }, - "node_modules/array-includes": { - "version": "3.1.5", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.19.5", - "get-intrinsic": "^1.1.1", - "is-string": "^1.0.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array-union": { - "version": "2.1.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/array.prototype.every": { - "version": "1.1.3", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.0", - "is-string": "^1.0.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.find": { - "version": "2.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.4", - "es-shim-unscopables": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.flat": { - "version": "1.3.0", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.2", - "es-shim-unscopables": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/asap": { - "version": "2.0.6", - "dev": true, - "license": "MIT" - }, - "node_modules/asn1": { - "version": "0.2.6", - "license": "MIT", - "dependencies": { - "safer-buffer": "~2.1.0" - } - }, - "node_modules/asn1.js": { - "version": "5.4.1", - "license": "MIT", - "dependencies": { - "bn.js": "^4.0.0", - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0", - "safer-buffer": "^2.1.0" - } - }, - "node_modules/asn1.js/node_modules/bn.js": { - "version": "4.12.0", - "license": "MIT" - }, - "node_modules/assert": { - "version": "1.5.0", - "dev": true, - "license": "MIT", - "dependencies": { - "object-assign": "^4.1.1", - "util": "0.10.3" - } - }, - "node_modules/assert-plus": { - "version": "1.0.0", - "license": "MIT", - "engines": { - "node": ">=0.8" - } - }, - "node_modules/assert/node_modules/inherits": { - "version": "2.0.1", - "dev": true, - "license": "ISC" - }, - "node_modules/assert/node_modules/util": { - "version": "0.10.3", - "dev": true, - "license": "MIT", - "dependencies": { - "inherits": "2.0.1" - } - }, - "node_modules/assertion-error": { - "version": "1.1.0", - "license": "MIT", - "engines": { - "node": "*" - } - }, - "node_modules/ast-types-flow": { - "version": "0.0.7", - "dev": true, - "license": "ISC" - }, - "node_modules/astral-regex": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/async": { - "version": "3.2.4", - "license": "MIT" - }, - "node_modules/asynckit": { - "version": "0.4.0", - "license": "MIT" - }, - "node_modules/atomic-sleep": { - "version": "1.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/available-typed-arrays": { - "version": "1.0.5", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/aws-sign2": { - "version": "0.7.0", - "license": "Apache-2.0", - "engines": { - "node": "*" - } - }, - "node_modules/aws4": { - "version": "1.11.0", - "license": "MIT" - }, - "node_modules/axe-core": { - "version": "4.4.3", - "dev": true, - "license": "MPL-2.0", - "engines": { - "node": ">=4" - } - }, - "node_modules/axobject-query": { - "version": "2.2.0", - "dev": true, - "license": "Apache-2.0" - }, - "node_modules/babel-code-frame": { - "version": "6.26.0", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^1.1.3", - "esutils": "^2.0.2", - "js-tokens": "^3.0.2" - } - }, - "node_modules/babel-code-frame/node_modules/ansi-regex": { - "version": "2.1.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/babel-code-frame/node_modules/ansi-styles": { - "version": "2.2.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/babel-code-frame/node_modules/chalk": { - "version": "1.1.3", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/babel-code-frame/node_modules/js-tokens": { - "version": "3.0.2", - "dev": true, - "license": "MIT" - }, - "node_modules/babel-code-frame/node_modules/strip-ansi": { - "version": "3.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/babel-code-frame/node_modules/supports-color": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/babel-plugin-polyfill-corejs2": { - "version": "0.3.3", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/compat-data": "^7.17.7", - "@babel/helper-define-polyfill-provider": "^0.3.3", - "semver": "^6.1.1" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": { - "version": "6.3.0", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.6.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.3.3", - "core-js-compat": "^3.25.1" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/babel-plugin-polyfill-regenerator": { - "version": "0.4.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.3.3" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/babel-polyfill": { - "version": "6.26.0", - "dev": true, - "license": "MIT", - "dependencies": { - "babel-runtime": "^6.26.0", - "core-js": "^2.5.0", - "regenerator-runtime": "^0.10.5" - } - }, - "node_modules/babel-polyfill/node_modules/regenerator-runtime": { - "version": "0.10.5", - "dev": true, - "license": "MIT" - }, - "node_modules/babel-runtime": { - "version": "6.26.0", - "dev": true, - "license": "MIT", - "dependencies": { - "core-js": "^2.4.0", - "regenerator-runtime": "^0.11.0" - } - }, - "node_modules/babel-runtime/node_modules/regenerator-runtime": { - "version": "0.11.1", - "dev": true, - "license": "MIT" - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "license": "MIT" - }, - "node_modules/base32.js": { - "version": "0.1.0", - "license": "MIT", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/base64-js": { - "version": "1.5.1", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/base64id": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": "^4.5.0 || >= 5.9" - } - }, - "node_modules/bcrypt-pbkdf": { - "version": "1.0.2", - "license": "BSD-3-Clause", - "dependencies": { - "tweetnacl": "^0.14.3" - } - }, - "node_modules/bech32": { - "version": "1.1.4", - "license": "MIT" - }, - "node_modules/benchmark": { - "version": "2.1.4", - "dev": true, - "license": "MIT", - "dependencies": { - "lodash": "^4.17.4", - "platform": "^1.3.3" - } - }, - "node_modules/big.js": { - "version": "5.2.2", - "dev": true, - "license": "MIT", - "engines": { - "node": "*" - } - }, - "node_modules/bigint-crypto-utils": { - "version": "3.1.7", - "license": "MIT", - "dependencies": { - "bigint-mod-arith": "^3.1.0" - }, - "engines": { - "node": ">=10.4.0" - } - }, - "node_modules/bigint-mod-arith": { - "version": "3.1.2", - "license": "MIT", - "engines": { - "node": ">=10.4.0" - } - }, - "node_modules/bignumber.js": { - "version": "9.1.0", - "license": "MIT", - "engines": { - "node": "*" - } - }, - "node_modules/binary-extensions": { - "version": "2.2.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/bindings": { - "version": "1.5.0", - "license": "MIT", - "dependencies": { - "file-uri-to-path": "1.0.0" - } - }, - "node_modules/blakejs": { - "version": "1.2.1", - "license": "MIT" - }, - "node_modules/bn.js": { - "version": "5.2.1", - "license": "MIT" - }, - "node_modules/body-parser": { - "version": "1.20.1", - "license": "MIT", - "dependencies": { - "bytes": "3.1.2", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.11.0", - "raw-body": "2.5.1", - "type-is": "~1.6.18", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/body-parser/node_modules/debug": { - "version": "2.6.9", - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/body-parser/node_modules/ms": { - "version": "2.0.0", - "license": "MIT" - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "3.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "fill-range": "^7.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/brorand": { - "version": "1.1.0", - "license": "MIT" - }, - "node_modules/browser-level": { - "version": "1.0.1", - "license": "MIT", - "dependencies": { - "abstract-level": "^1.0.2", - "catering": "^2.1.1", - "module-error": "^1.0.2", - "run-parallel-limit": "^1.1.0" - } - }, - "node_modules/browser-pack": { - "version": "6.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "combine-source-map": "~0.8.0", - "defined": "^1.0.0", - "JSONStream": "^1.0.3", - "safe-buffer": "^5.1.1", - "through2": "^2.0.0", - "umd": "^3.0.0" - }, - "bin": { - "browser-pack": "bin/cmd.js" - } - }, - "node_modules/browser-process-hrtime": { - "version": "0.1.3", - "dev": true, - "license": "BSD-2-Clause" - }, - "node_modules/browser-resolve": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "resolve": "^1.17.0" - } - }, - "node_modules/browserify": { - "version": "16.5.2", - "dev": true, - "license": "MIT", - "dependencies": { - "assert": "^1.4.0", - "browser-pack": "^6.0.1", - "browser-resolve": "^2.0.0", - "browserify-zlib": "~0.2.0", - "buffer": "~5.2.1", - "cached-path-relative": "^1.0.0", - "concat-stream": "^1.6.0", - "console-browserify": "^1.1.0", - "constants-browserify": "~1.0.0", - "crypto-browserify": "^3.0.0", - "defined": "^1.0.0", - "deps-sort": "^2.0.0", - "domain-browser": "^1.2.0", - "duplexer2": "~0.1.2", - "events": "^2.0.0", - "glob": "^7.1.0", - "has": "^1.0.0", - "htmlescape": "^1.1.0", - "https-browserify": "^1.0.0", - "inherits": "~2.0.1", - "insert-module-globals": "^7.0.0", - "JSONStream": "^1.0.3", - "labeled-stream-splicer": "^2.0.0", - "mkdirp-classic": "^0.5.2", - "module-deps": "^6.2.3", - "os-browserify": "~0.3.0", - "parents": "^1.0.1", - "path-browserify": "~0.0.0", - "process": "~0.11.0", - "punycode": "^1.3.2", - "querystring-es3": "~0.2.0", - "read-only-stream": "^2.0.0", - "readable-stream": "^2.0.2", - "resolve": "^1.1.4", - "shasum": "^1.0.0", - "shell-quote": "^1.6.1", - "stream-browserify": "^2.0.0", - "stream-http": "^3.0.0", - "string_decoder": "^1.1.1", - "subarg": "^1.0.0", - "syntax-error": "^1.1.1", - "through2": "^2.0.0", - "timers-browserify": "^1.0.1", - "tty-browserify": "0.0.1", - "url": "~0.11.0", - "util": "~0.10.1", - "vm-browserify": "^1.0.0", - "xtend": "^4.0.0" - }, - "bin": { - "browserify": "bin/cmd.js" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/browserify-aes": { - "version": "1.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "buffer-xor": "^1.0.3", - "cipher-base": "^1.0.0", - "create-hash": "^1.1.0", - "evp_bytestokey": "^1.0.3", - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/browserify-cipher": { - "version": "1.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "browserify-aes": "^1.0.4", - "browserify-des": "^1.0.0", - "evp_bytestokey": "^1.0.0" - } - }, - "node_modules/browserify-des": { - "version": "1.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "cipher-base": "^1.0.1", - "des.js": "^1.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "node_modules/browserify-rsa": { - "version": "4.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "bn.js": "^5.0.0", - "randombytes": "^2.0.1" - } - }, - "node_modules/browserify-sign": { - "version": "4.2.1", - "dev": true, - "license": "ISC", - "dependencies": { - "bn.js": "^5.1.1", - "browserify-rsa": "^4.0.1", - "create-hash": "^1.2.0", - "create-hmac": "^1.1.7", - "elliptic": "^6.5.3", - "inherits": "^2.0.4", - "parse-asn1": "^5.1.5", - "readable-stream": "^3.6.0", - "safe-buffer": "^5.2.0" - } - }, - "node_modules/browserify-sign/node_modules/readable-stream": { - "version": "3.6.0", - "dev": true, - "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/browserify-zlib": { - "version": "0.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "pako": "~1.0.5" - } - }, - "node_modules/browserify/node_modules/buffer": { - "version": "5.2.1", - "dev": true, - "license": "MIT", - "dependencies": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4" - } - }, - "node_modules/browserify/node_modules/inherits": { - "version": "2.0.3", - "dev": true, - "license": "ISC" - }, - "node_modules/browserify/node_modules/stream-browserify": { - "version": "2.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "inherits": "~2.0.1", - "readable-stream": "^2.0.2" - } - }, - "node_modules/browserify/node_modules/util": { - "version": "0.10.4", - "dev": true, - "license": "MIT", - "dependencies": { - "inherits": "2.0.3" - } - }, - "node_modules/browserslist": { - "version": "4.21.4", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - } - ], - "license": "MIT", - "dependencies": { - "caniuse-lite": "^1.0.30001400", - "electron-to-chromium": "^1.4.251", - "node-releases": "^2.0.6", - "update-browserslist-db": "^1.0.9" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "node_modules/buffer": { - "version": "6.0.3", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, - "node_modules/buffer-from": { - "version": "1.1.2", - "dev": true, - "license": "MIT" - }, - "node_modules/buffer-xor": { - "version": "1.0.3", - "dev": true, - "license": "MIT" - }, - "node_modules/builtin-modules": { - "version": "1.1.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/builtin-status-codes": { - "version": "3.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/bytes": { - "version": "3.1.2", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/c-kzg": { - "version": "2.0.4", - "license": "MIT", - "dependencies": { - "bindings": "^1.5.0", - "node-addon-api": "^5.0.0" - } - }, - "node_modules/c-kzg/node_modules/node-addon-api": { - "version": "5.1.0", - "license": "MIT" - }, - "node_modules/c8": { - "version": "7.12.0", - "dev": true, - "license": "ISC", - "dependencies": { - "@bcoe/v8-coverage": "^0.2.3", - "@istanbuljs/schema": "^0.1.3", - "find-up": "^5.0.0", - "foreground-child": "^2.0.0", - "istanbul-lib-coverage": "^3.2.0", - "istanbul-lib-report": "^3.0.0", - "istanbul-reports": "^3.1.4", - "rimraf": "^3.0.2", - "test-exclude": "^6.0.0", - "v8-to-istanbul": "^9.0.0", - "yargs": "^16.2.0", - "yargs-parser": "^20.2.9" - }, - "bin": { - "c8": "bin/c8.js" - }, - "engines": { - "node": ">=10.12.0" - } - }, - "node_modules/cached-path-relative": { - "version": "1.1.0", - "dev": true, - "license": "MIT" - }, - "node_modules/caching-transform": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "hasha": "^5.0.0", - "make-dir": "^3.0.0", - "package-hash": "^4.0.0", - "write-file-atomic": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/caching-transform/node_modules/make-dir": { - "version": "3.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "semver": "^6.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/caching-transform/node_modules/semver": { - "version": "6.3.0", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/call-bind": { - "version": "1.0.2", - "license": "MIT", - "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/caller-path": { - "version": "0.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "callsites": "^0.2.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/caller-path/node_modules/callsites": { - "version": "0.2.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/callsites": { - "version": "3.1.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/camel-case": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "no-case": "^2.2.0", - "upper-case": "^1.1.1" - } - }, - "node_modules/camelcase": { - "version": "5.3.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001423", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - } - ], - "license": "CC-BY-4.0" - }, - "node_modules/caseless": { - "version": "0.12.0", - "license": "Apache-2.0" - }, - "node_modules/catering": { - "version": "2.1.1", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/chai": { - "version": "4.3.6", - "license": "MIT", - "dependencies": { - "assertion-error": "^1.1.0", - "check-error": "^1.0.2", - "deep-eql": "^3.0.1", - "get-func-name": "^2.0.0", - "loupe": "^2.3.1", - "pathval": "^1.1.1", - "type-detect": "^4.0.5" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/chai-checkmark": { - "version": "1.0.1", - "license": "ISC" - }, - "node_modules/chalk": { - "version": "4.1.2", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/check-error": { - "version": "1.0.2", - "license": "MIT", - "engines": { - "node": "*" - } - }, - "node_modules/chokidar": { - "version": "3.5.3", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], - "license": "MIT", - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/chokidar/node_modules/glob-parent": { - "version": "5.1.2", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/chrome-trace-event": { - "version": "1.0.3", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.0" - } - }, - "node_modules/cids": { - "version": "1.1.9", - "license": "MIT", - "dependencies": { - "multibase": "^4.0.1", - "multicodec": "^3.0.1", - "multihashes": "^4.0.1", - "uint8arrays": "^3.0.0" - }, - "engines": { - "node": ">=4.0.0", - "npm": ">=3.0.0" - } - }, - "node_modules/cids/node_modules/multicodec": { - "version": "3.2.1", - "license": "MIT", - "dependencies": { - "uint8arrays": "^3.0.0", - "varint": "^6.0.0" - } - }, - "node_modules/cipher-base": { - "version": "1.0.4", - "dev": true, - "license": "MIT", - "dependencies": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/circular-json": { - "version": "0.3.3", - "dev": true, - "license": "MIT" - }, - "node_modules/class-is": { - "version": "1.1.0", - "license": "MIT" - }, - "node_modules/classic-level": { - "version": "1.2.0", - "hasInstallScript": true, - "license": "MIT", - "dependencies": { - "abstract-level": "^1.0.2", - "catering": "^2.1.0", - "module-error": "^1.0.1", - "napi-macros": "~2.0.0", - "node-gyp-build": "^4.3.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/clean-stack": { - "version": "2.2.0", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/cli-cursor": { - "version": "3.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "restore-cursor": "^3.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cli-truncate": { - "version": "3.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "slice-ansi": "^5.0.0", - "string-width": "^5.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cli-width": { - "version": "2.2.1", - "dev": true, - "license": "ISC" - }, - "node_modules/cliui": { - "version": "7.0.4", - "dev": true, - "license": "ISC", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "node_modules/cliui/node_modules/emoji-regex": { - "version": "8.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/cliui/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/cliui/node_modules/string-width": { - "version": "4.2.3", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/clone": { - "version": "1.0.4", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8" - } - }, - "node_modules/clone-deep": { - "version": "4.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "is-plain-object": "^2.0.4", - "kind-of": "^6.0.2", - "shallow-clone": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/co": { - "version": "4.6.0", - "dev": true, - "license": "MIT", - "engines": { - "iojs": ">= 1.0.0", - "node": ">= 0.12.0" - } - }, - "node_modules/code-point-at": { - "version": "1.1.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/color": { - "version": "3.2.1", - "license": "MIT", - "dependencies": { - "color-convert": "^1.9.3", - "color-string": "^1.6.0" - } - }, - "node_modules/color-convert": { - "version": "2.0.1", - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "license": "MIT" - }, - "node_modules/color-string": { - "version": "1.9.1", - "license": "MIT", - "dependencies": { - "color-name": "^1.0.0", - "simple-swizzle": "^0.2.2" - } - }, - "node_modules/color/node_modules/color-convert": { - "version": "1.9.3", - "license": "MIT", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/color/node_modules/color-name": { - "version": "1.1.3", - "license": "MIT" - }, - "node_modules/colorette": { - "version": "2.0.19", - "dev": true, - "license": "MIT" - }, - "node_modules/colors": { - "version": "0.6.2", - "dev": true, - "engines": { - "node": ">=0.1.90" - } - }, - "node_modules/colorspace": { - "version": "1.1.4", - "license": "MIT", - "dependencies": { - "color": "^3.1.3", - "text-hex": "1.0.x" - } - }, - "node_modules/combine-source-map": { - "version": "0.8.0", - "dev": true, - "license": "MIT", - "dependencies": { - "convert-source-map": "~1.1.0", - "inline-source-map": "~0.6.0", - "lodash.memoize": "~3.0.3", - "source-map": "~0.5.3" - } - }, - "node_modules/combined-stream": { - "version": "1.0.8", - "license": "MIT", - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/command-exists": { - "version": "1.2.9", - "dev": true, - "license": "MIT" - }, - "node_modules/commander": { - "version": "2.1.0", - "dev": true, - "engines": { - "node": ">= 0.6.x" - } - }, - "node_modules/commondir": { - "version": "1.0.1", - "dev": true, - "license": "MIT" - }, - "node_modules/component-emitter": { - "version": "1.3.0", - "dev": true, - "license": "MIT" - }, - "node_modules/concat-map": { - "version": "0.0.1", - "license": "MIT" - }, - "node_modules/concat-stream": { - "version": "1.6.2", - "dev": true, - "engines": [ - "node >= 0.8" - ], - "license": "MIT", - "dependencies": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" - } - }, - "node_modules/connect": { - "version": "3.7.0", - "license": "MIT", - "dependencies": { - "debug": "2.6.9", - "finalhandler": "1.1.2", - "parseurl": "~1.3.3", - "utils-merge": "1.0.1" - }, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/connect/node_modules/debug": { - "version": "2.6.9", - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/connect/node_modules/ms": { - "version": "2.0.0", - "license": "MIT" - }, - "node_modules/console-browserify": { - "version": "1.2.0", - "dev": true - }, - "node_modules/constants-browserify": { - "version": "1.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/contains-path": { - "version": "0.1.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/content-type": { - "version": "1.0.4", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/convert-source-map": { - "version": "1.1.3", - "dev": true, - "license": "MIT" - }, - "node_modules/cookie": { - "version": "0.4.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookiejar": { - "version": "2.1.3", - "dev": true, - "license": "MIT" - }, - "node_modules/core-js": { - "version": "2.6.12", - "dev": true, - "hasInstallScript": true, - "license": "MIT" - }, - "node_modules/core-js-compat": { - "version": "3.25.5", - "dev": true, - "license": "MIT", - "dependencies": { - "browserslist": "^4.21.4" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/core-js" - } - }, - "node_modules/core-js-pure": { - "version": "3.25.5", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/core-js" - } - }, - "node_modules/core-util-is": { - "version": "1.0.3", - "dev": true, - "license": "MIT" - }, - "node_modules/cors": { - "version": "2.8.5", - "license": "MIT", - "dependencies": { - "object-assign": "^4", - "vary": "^1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/crc-32": { - "version": "1.2.2", - "license": "Apache-2.0", - "bin": { - "crc32": "bin/crc32.njs" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/create-ecdh": { - "version": "4.0.4", - "dev": true, - "license": "MIT", - "dependencies": { - "bn.js": "^4.1.0", - "elliptic": "^6.5.3" - } - }, - "node_modules/create-ecdh/node_modules/bn.js": { - "version": "4.12.0", - "dev": true, - "license": "MIT" - }, - "node_modules/create-hash": { - "version": "1.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "cipher-base": "^1.0.1", - "inherits": "^2.0.1", - "md5.js": "^1.3.4", - "ripemd160": "^2.0.1", - "sha.js": "^2.4.0" - } - }, - "node_modules/create-hmac": { - "version": "1.1.7", - "dev": true, - "license": "MIT", - "dependencies": { - "cipher-base": "^1.0.3", - "create-hash": "^1.1.0", - "inherits": "^2.0.1", - "ripemd160": "^2.0.0", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - } - }, - "node_modules/create-require": { - "version": "1.1.1", - "dev": true, - "license": "MIT" - }, - "node_modules/cross-spawn": { - "version": "7.0.3", - "license": "MIT", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/cross-spawn/node_modules/which": { - "version": "2.0.2", - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/crypto-browserify": { - "version": "3.12.0", - "dev": true, - "license": "MIT", - "dependencies": { - "browserify-cipher": "^1.0.0", - "browserify-sign": "^4.0.0", - "create-ecdh": "^4.0.0", - "create-hash": "^1.1.0", - "create-hmac": "^1.1.0", - "diffie-hellman": "^5.0.0", - "inherits": "^2.0.1", - "pbkdf2": "^3.0.3", - "public-encrypt": "^4.0.0", - "randombytes": "^2.0.0", - "randomfill": "^1.0.3" - }, - "engines": { - "node": "*" - } - }, - "node_modules/custom-event": { - "version": "1.0.1", - "dev": true, - "license": "MIT" - }, - "node_modules/d": { - "version": "1.0.1", - "dev": true, - "license": "ISC", - "dependencies": { - "es5-ext": "^0.10.50", - "type": "^1.0.1" - } - }, - "node_modules/d3-array": { - "version": "2.12.1", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "internmap": "^1.0.0" - } - }, - "node_modules/d3-color": { - "version": "2.0.0", - "dev": true, - "license": "BSD-3-Clause" - }, - "node_modules/d3-dispatch": { - "version": "1.0.6", - "dev": true, - "license": "BSD-3-Clause" - }, - "node_modules/d3-drag": { - "version": "1.2.5", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "d3-dispatch": "1", - "d3-selection": "1" - } - }, - "node_modules/d3-ease": { - "version": "1.0.7", - "dev": true, - "license": "BSD-3-Clause" - }, - "node_modules/d3-fg": { - "version": "6.14.0", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "d3-array": "^2.2.0", - "d3-dispatch": "^1.0.5", - "d3-ease": "^1.0.5", - "d3-hierarchy": "^1.1.8", - "d3-scale": "^3.0.0", - "d3-selection": "^1.4.0", - "d3-zoom": "^1.7.3", - "escape-string-regexp": "^1.0.5", - "hsl-to-rgb-for-reals": "^1.1.0" - } - }, - "node_modules/d3-format": { - "version": "2.0.0", - "dev": true, - "license": "BSD-3-Clause" - }, - "node_modules/d3-hierarchy": { - "version": "1.1.9", - "dev": true, - "license": "BSD-3-Clause" - }, - "node_modules/d3-interpolate": { - "version": "2.0.1", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "d3-color": "1 - 2" - } - }, - "node_modules/d3-scale": { - "version": "3.3.0", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "d3-array": "^2.3.0", - "d3-format": "1 - 2", - "d3-interpolate": "1.2.0 - 2", - "d3-time": "^2.1.1", - "d3-time-format": "2 - 3" - } - }, - "node_modules/d3-selection": { - "version": "1.4.2", - "dev": true, - "license": "BSD-3-Clause" - }, - "node_modules/d3-time": { - "version": "2.1.1", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "d3-array": "2" - } - }, - "node_modules/d3-time-format": { - "version": "3.0.0", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "d3-time": "1 - 2" - } - }, - "node_modules/d3-timer": { - "version": "1.0.10", - "dev": true, - "license": "BSD-3-Clause" - }, - "node_modules/d3-transition": { - "version": "1.3.2", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "d3-color": "1", - "d3-dispatch": "1", - "d3-ease": "1", - "d3-interpolate": "1", - "d3-selection": "^1.1.0", - "d3-timer": "1" - } - }, - "node_modules/d3-transition/node_modules/d3-color": { - "version": "1.4.1", - "dev": true, - "license": "BSD-3-Clause" - }, - "node_modules/d3-transition/node_modules/d3-interpolate": { - "version": "1.4.0", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "d3-color": "1" - } - }, - "node_modules/d3-zoom": { - "version": "1.8.3", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "d3-dispatch": "1", - "d3-drag": "1", - "d3-interpolate": "1", - "d3-selection": "1", - "d3-transition": "1" - } - }, - "node_modules/d3-zoom/node_modules/d3-color": { - "version": "1.4.1", - "dev": true, - "license": "BSD-3-Clause" - }, - "node_modules/d3-zoom/node_modules/d3-interpolate": { - "version": "1.4.0", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "d3-color": "1" - } - }, - "node_modules/damerau-levenshtein": { - "version": "1.0.8", - "dev": true, - "license": "BSD-2-Clause" - }, - "node_modules/dash-ast": { - "version": "1.0.0", - "dev": true, - "license": "Apache-2.0" - }, - "node_modules/dashdash": { - "version": "1.14.1", - "license": "MIT", - "dependencies": { - "assert-plus": "^1.0.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/date-format": { - "version": "4.0.14", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/debounce": { - "version": "1.2.1", - "dev": true, - "license": "MIT" - }, - "node_modules/debug": { - "version": "4.3.4", - "license": "MIT", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/debug-log": { - "version": "1.0.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/debug/node_modules/ms": { - "version": "2.1.2", - "license": "MIT" - }, - "node_modules/decamelize": { - "version": "1.2.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/deep-eql": { - "version": "3.0.1", - "license": "MIT", - "dependencies": { - "type-detect": "^4.0.0" - }, - "engines": { - "node": ">=0.12" - } - }, - "node_modules/deep-equal": { - "version": "2.0.5", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.0", - "es-get-iterator": "^1.1.1", - "get-intrinsic": "^1.0.1", - "is-arguments": "^1.0.4", - "is-date-object": "^1.0.2", - "is-regex": "^1.1.1", - "isarray": "^2.0.5", - "object-is": "^1.1.4", - "object-keys": "^1.1.1", - "object.assign": "^4.1.2", - "regexp.prototype.flags": "^1.3.0", - "side-channel": "^1.0.3", - "which-boxed-primitive": "^1.0.1", - "which-collection": "^1.0.1", - "which-typed-array": "^1.1.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/deep-equal/node_modules/isarray": { - "version": "2.0.5", - "dev": true, - "license": "MIT" - }, - "node_modules/deep-is": { - "version": "0.1.4", - "dev": true, - "license": "MIT" - }, - "node_modules/default-gateway": { - "version": "6.0.3", - "license": "BSD-2-Clause", - "dependencies": { - "execa": "^5.0.0" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/default-require-extensions": { - "version": "3.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "strip-bom": "^4.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/defaults": { - "version": "1.0.4", - "dev": true, - "license": "MIT", - "dependencies": { - "clone": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/deferred-leveldown": { - "version": "7.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "abstract-leveldown": "^7.2.0", - "inherits": "^2.0.3" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/define-properties": { - "version": "1.1.4", - "license": "MIT", - "dependencies": { - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/defined": { - "version": "1.0.1", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/deglob": { - "version": "2.1.1", - "dev": true, - "license": "ISC", - "dependencies": { - "find-root": "^1.0.0", - "glob": "^7.0.5", - "ignore": "^3.0.9", - "pkg-config": "^1.1.0", - "run-parallel": "^1.1.2", - "uniq": "^1.0.1" - } - }, - "node_modules/deglob/node_modules/ignore": { - "version": "3.3.10", - "dev": true, - "license": "MIT" - }, - "node_modules/delay": { - "version": "5.0.0", - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "license": "MIT", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/depd": { - "version": "2.0.0", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/deps-sort": { - "version": "2.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "JSONStream": "^1.0.3", - "shasum-object": "^1.0.0", - "subarg": "^1.0.0", - "through2": "^2.0.0" - }, - "bin": { - "deps-sort": "bin/cmd.js" - } - }, - "node_modules/des.js": { - "version": "1.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0" - } - }, - "node_modules/destroy": { - "version": "1.2.0", - "license": "MIT", - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/detect-indent": { - "version": "6.1.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/detect-newline": { - "version": "3.1.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/detect-node": { - "version": "2.1.0", - "license": "MIT" - }, - "node_modules/detective": { - "version": "5.2.1", - "dev": true, - "license": "MIT", - "dependencies": { - "acorn-node": "^1.8.2", - "defined": "^1.0.0", - "minimist": "^1.2.6" - }, - "bin": { - "detective": "bin/detective.js" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/dezalgo": { - "version": "1.0.3", - "dev": true, - "license": "ISC", - "dependencies": { - "asap": "^2.0.0", - "wrappy": "1" - } - }, - "node_modules/di": { - "version": "0.0.1", - "dev": true, - "license": "MIT" - }, - "node_modules/diff": { - "version": "4.0.2", - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/diffie-hellman": { - "version": "5.0.3", - "dev": true, - "license": "MIT", - "dependencies": { - "bn.js": "^4.1.0", - "miller-rabin": "^4.0.0", - "randombytes": "^2.0.0" - } - }, - "node_modules/diffie-hellman/node_modules/bn.js": { - "version": "4.12.0", - "dev": true, - "license": "MIT" - }, - "node_modules/dir-glob": { - "version": "3.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/dirty-chai": { - "version": "2.0.1", - "license": "MIT", - "peerDependencies": { - "chai": ">=2.2.1 <5" - } - }, - "node_modules/dns-over-http-resolver": { - "version": "1.2.3", - "license": "MIT", - "dependencies": { - "debug": "^4.3.1", - "native-fetch": "^3.0.0", - "receptacle": "^1.3.2" - } - }, - "node_modules/doctrine": { - "version": "3.0.0", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/dom-serialize": { - "version": "2.2.1", - "dev": true, - "license": "MIT", - "dependencies": { - "custom-event": "~1.0.0", - "ent": "~2.2.0", - "extend": "^3.0.0", - "void-elements": "^2.0.0" - } - }, - "node_modules/domain-browser": { - "version": "1.2.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.4", - "npm": ">=1.2" - } - }, - "node_modules/dotignore": { - "version": "0.1.2", - "dev": true, - "license": "MIT", - "dependencies": { - "minimatch": "^3.0.4" - }, - "bin": { - "ignored": "bin/ignored" - } - }, - "node_modules/duplexer2": { - "version": "0.1.4", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "readable-stream": "^2.0.2" - } - }, - "node_modules/duplexify": { - "version": "3.7.1", - "dev": true, - "license": "MIT", - "dependencies": { - "end-of-stream": "^1.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.0.0", - "stream-shift": "^1.0.0" - } - }, - "node_modules/eastasianwidth": { - "version": "0.2.0", - "dev": true, - "license": "MIT" - }, - "node_modules/ecc-jsbn": { - "version": "0.1.2", - "license": "MIT", - "dependencies": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, - "node_modules/ecc-jsbn/node_modules/jsbn": { - "version": "0.1.1", - "license": "MIT" - }, - "node_modules/ee-first": { - "version": "1.1.1", - "license": "MIT" - }, - "node_modules/electron-fetch": { - "version": "1.9.1", - "license": "MIT", - "dependencies": { - "encoding": "^0.1.13" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/electron-to-chromium": { - "version": "1.4.284", - "dev": true, - "license": "ISC" - }, - "node_modules/elliptic": { - "version": "6.5.4", - "license": "MIT", - "dependencies": { - "bn.js": "^4.11.9", - "brorand": "^1.1.0", - "hash.js": "^1.0.0", - "hmac-drbg": "^1.0.1", - "inherits": "^2.0.4", - "minimalistic-assert": "^1.0.1", - "minimalistic-crypto-utils": "^1.0.1" - } - }, - "node_modules/elliptic/node_modules/bn.js": { - "version": "4.12.0", - "license": "MIT" - }, - "node_modules/emoji-regex": { - "version": "9.2.2", - "dev": true, - "license": "MIT" - }, - "node_modules/emojis-list": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/enabled": { - "version": "2.0.0", - "license": "MIT" - }, - "node_modules/encodeurl": { - "version": "1.0.2", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/encoding": { - "version": "0.1.13", - "license": "MIT", - "dependencies": { - "iconv-lite": "^0.6.2" - } - }, - "node_modules/encoding-down": { - "version": "7.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "abstract-leveldown": "^7.2.0", - "inherits": "^2.0.3", - "level-codec": "^10.0.0", - "level-errors": "^3.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/encoding/node_modules/iconv-lite": { - "version": "0.6.3", - "license": "MIT", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/end-of-stream": { - "version": "1.4.4", - "dev": true, - "license": "MIT", - "dependencies": { - "once": "^1.4.0" - } - }, - "node_modules/engine.io": { - "version": "6.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/cookie": "^0.4.1", - "@types/cors": "^2.8.12", - "@types/node": ">=10.0.0", - "accepts": "~1.3.4", - "base64id": "2.0.0", - "cookie": "~0.4.1", - "cors": "~2.8.5", - "debug": "~4.3.1", - "engine.io-parser": "~5.0.3", - "ws": "~8.2.3" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/engine.io-parser": { - "version": "5.0.4", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/engine.io/node_modules/ws": { - "version": "8.2.3", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/enhanced-resolve": { - "version": "5.10.0", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/ent": { - "version": "2.2.0", - "dev": true, - "license": "MIT" - }, - "node_modules/env-string": { - "version": "1.0.1", - "dev": true, - "license": "MIT" - }, - "node_modules/envinfo": { - "version": "7.8.1", - "dev": true, - "license": "MIT", - "bin": { - "envinfo": "dist/cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/err-code": { - "version": "2.0.3", - "license": "MIT" - }, - "node_modules/error-ex": { - "version": "1.3.2", - "dev": true, - "license": "MIT", - "dependencies": { - "is-arrayish": "^0.2.1" - } - }, - "node_modules/es-abstract": { - "version": "1.20.4", - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "function.prototype.name": "^1.1.5", - "get-intrinsic": "^1.1.3", - "get-symbol-description": "^1.0.0", - "has": "^1.0.3", - "has-property-descriptors": "^1.0.0", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.3", - "is-callable": "^1.2.7", - "is-negative-zero": "^2.0.2", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", - "is-string": "^1.0.7", - "is-weakref": "^1.0.2", - "object-inspect": "^1.12.2", - "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.4.3", - "safe-regex-test": "^1.0.0", - "string.prototype.trimend": "^1.0.5", - "string.prototype.trimstart": "^1.0.5", - "unbox-primitive": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-get-iterator": { - "version": "1.1.2", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.0", - "has-symbols": "^1.0.1", - "is-arguments": "^1.1.0", - "is-map": "^2.0.2", - "is-set": "^2.0.2", - "is-string": "^1.0.5", - "isarray": "^2.0.5" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-get-iterator/node_modules/isarray": { - "version": "2.0.5", - "dev": true, - "license": "MIT" - }, - "node_modules/es-module-lexer": { - "version": "0.9.3", - "dev": true, - "license": "MIT" - }, - "node_modules/es-shim-unscopables": { - "version": "1.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "has": "^1.0.3" - } - }, - "node_modules/es-to-primitive": { - "version": "1.2.1", - "license": "MIT", - "dependencies": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es5-ext": { - "version": "0.10.62", - "dev": true, - "hasInstallScript": true, - "license": "ISC", - "dependencies": { - "es6-iterator": "^2.0.3", - "es6-symbol": "^3.1.3", - "next-tick": "^1.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/es6-error": { - "version": "4.1.1", - "dev": true, - "license": "MIT" - }, - "node_modules/es6-iterator": { - "version": "2.0.3", - "dev": true, - "license": "MIT", - "dependencies": { - "d": "1", - "es5-ext": "^0.10.35", - "es6-symbol": "^3.1.1" - } - }, - "node_modules/es6-map": { - "version": "0.1.5", - "dev": true, - "license": "MIT", - "dependencies": { - "d": "1", - "es5-ext": "~0.10.14", - "es6-iterator": "~2.0.1", - "es6-set": "~0.1.5", - "es6-symbol": "~3.1.1", - "event-emitter": "~0.3.5" - } - }, - "node_modules/es6-object-assign": { - "version": "1.1.0", - "dev": true, - "license": "MIT" - }, - "node_modules/es6-promise": { - "version": "4.2.8", - "license": "MIT" - }, - "node_modules/es6-promisify": { - "version": "5.0.0", - "license": "MIT", - "dependencies": { - "es6-promise": "^4.0.3" - } - }, - "node_modules/es6-set": { - "version": "0.1.6", - "dev": true, - "license": "ISC", - "dependencies": { - "d": "^1.0.1", - "es5-ext": "^0.10.62", - "es6-iterator": "~2.0.3", - "es6-symbol": "^3.1.3", - "event-emitter": "^0.3.5", - "type": "^2.7.2" - }, - "engines": { - "node": ">=0.12" - } - }, - "node_modules/es6-set/node_modules/type": { - "version": "2.7.2", - "dev": true, - "license": "ISC" - }, - "node_modules/es6-symbol": { - "version": "3.1.3", - "dev": true, - "license": "ISC", - "dependencies": { - "d": "^1.0.1", - "ext": "^1.1.2" - } - }, - "node_modules/es6-weak-map": { - "version": "2.0.3", - "dev": true, - "license": "ISC", - "dependencies": { - "d": "1", - "es5-ext": "^0.10.46", - "es6-iterator": "^2.0.3", - "es6-symbol": "^3.1.1" - } - }, - "node_modules/escalade": { - "version": "3.1.1", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-html": { - "version": "1.0.3", - "license": "MIT" - }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/escope": { - "version": "3.6.0", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "es6-map": "^0.1.3", - "es6-weak-map": "^2.0.1", - "esrecurse": "^4.1.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/eslint": { - "version": "8.22.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint/eslintrc": "^1.3.0", - "@humanwhocodes/config-array": "^0.10.4", - "@humanwhocodes/gitignore-to-minimatch": "^1.0.2", - "ajv": "^6.10.0", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.1.1", - "eslint-utils": "^3.0.0", - "eslint-visitor-keys": "^3.3.0", - "espree": "^9.3.3", - "esquery": "^1.4.0", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "find-up": "^5.0.0", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^6.0.1", - "globals": "^13.15.0", - "globby": "^11.1.0", - "grapheme-splitter": "^1.0.4", - "ignore": "^5.2.0", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "regexpp": "^3.2.0", - "strip-ansi": "^6.0.1", - "strip-json-comments": "^3.1.0", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-config-prettier": { - "version": "8.5.0", - "dev": true, - "license": "MIT", - "bin": { - "eslint-config-prettier": "bin/cli.js" - }, - "peerDependencies": { - "eslint": ">=7.0.0" - } - }, - "node_modules/eslint-config-standard": { - "version": "10.2.1", - "dev": true, - "license": "MIT", - "peerDependencies": { - "eslint": ">=3.19.0", - "eslint-plugin-import": ">=2.2.0", - "eslint-plugin-node": ">=4.2.2", - "eslint-plugin-promise": ">=3.5.0", - "eslint-plugin-standard": ">=3.0.0" - } - }, - "node_modules/eslint-config-typestrict": { - "version": "1.0.5", - "dev": true, - "license": "MIT", - "peerDependencies": { - "@typescript-eslint/eslint-plugin": "^5", - "eslint-plugin-sonarjs": "*" - } - }, - "node_modules/eslint-formatter-codeframe": { - "version": "7.32.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "7.12.11", - "chalk": "^4.0.0" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/eslint-import-resolver-node": { - "version": "0.3.6", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^3.2.7", - "resolve": "^1.20.0" - } - }, - "node_modules/eslint-import-resolver-node/node_modules/debug": { - "version": "3.2.7", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-import-resolver-node/node_modules/ms": { - "version": "2.1.3", - "dev": true, - "license": "MIT" - }, - "node_modules/eslint-module-utils": { - "version": "2.7.4", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^3.2.7" - }, - "engines": { - "node": ">=4" - }, - "peerDependenciesMeta": { - "eslint": { - "optional": true - } - } - }, - "node_modules/eslint-module-utils/node_modules/debug": { - "version": "3.2.7", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-module-utils/node_modules/ms": { - "version": "2.1.3", - "dev": true, - "license": "MIT" - }, - "node_modules/eslint-plugin-escompat": { - "version": "3.3.4", - "dev": true, - "license": "MIT", - "dependencies": { - "browserslist": "^4.21.0" - }, - "peerDependencies": { - "eslint": ">=5.14.1" - } - }, - "node_modules/eslint-plugin-eslint-comments": { - "version": "3.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "escape-string-regexp": "^1.0.5", - "ignore": "^5.0.5" - }, - "engines": { - "node": ">=6.5.0" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - }, - "peerDependencies": { - "eslint": ">=4.19.1" - } - }, - "node_modules/eslint-plugin-ethereumjs": { - "resolved": "eslint", - "link": true - }, - "node_modules/eslint-plugin-filenames": { - "version": "1.3.2", - "dev": true, - "license": "MIT", - "dependencies": { - "lodash.camelcase": "4.3.0", - "lodash.kebabcase": "4.1.1", - "lodash.snakecase": "4.1.1", - "lodash.upperfirst": "4.3.1" - }, - "peerDependencies": { - "eslint": "*" - } - }, - "node_modules/eslint-plugin-github": { - "version": "4.3.7", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/eslint-plugin": "^5.1.0", - "@typescript-eslint/parser": "^5.1.0", - "eslint-config-prettier": ">=8.0.0", - "eslint-plugin-escompat": "^3.1.0", - "eslint-plugin-eslint-comments": "^3.2.0", - "eslint-plugin-filenames": "^1.3.2", - "eslint-plugin-i18n-text": "^1.0.1", - "eslint-plugin-import": "^2.25.2", - "eslint-plugin-jsx-a11y": "^6.6.0", - "eslint-plugin-no-only-tests": "^2.6.0", - "eslint-plugin-prettier": "^4.0.0", - "eslint-rule-documentation": ">=1.0.0", - "jsx-ast-utils": "^3.3.2", - "prettier": "^2.2.1", - "svg-element-attributes": "^1.3.1" - }, - "bin": { - "eslint-ignore-errors": "bin/eslint-ignore-errors.js" - }, - "peerDependencies": { - "eslint": "^8.0.1" - } - }, - "node_modules/eslint-plugin-i18n-text": { - "version": "1.0.1", - "dev": true, - "license": "MIT", - "peerDependencies": { - "eslint": ">=5.0.0" - } - }, - "node_modules/eslint-plugin-implicit-dependencies": { - "version": "1.1.1", - "dev": true, - "license": "MIT", - "dependencies": { - "builtin-modules": "^1.1.1", - "findup": "^0.1.5" - } - }, - "node_modules/eslint-plugin-import": { - "version": "2.26.0", - "dev": true, - "license": "MIT", - "dependencies": { - "array-includes": "^3.1.4", - "array.prototype.flat": "^1.2.5", - "debug": "^2.6.9", - "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.6", - "eslint-module-utils": "^2.7.3", - "has": "^1.0.3", - "is-core-module": "^2.8.1", - "is-glob": "^4.0.3", - "minimatch": "^3.1.2", - "object.values": "^1.1.5", - "resolve": "^1.22.0", - "tsconfig-paths": "^3.14.1" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" - } - }, - "node_modules/eslint-plugin-import/node_modules/debug": { - "version": "2.6.9", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/eslint-plugin-import/node_modules/doctrine": { - "version": "2.1.0", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/eslint-plugin-import/node_modules/ms": { - "version": "2.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/eslint-plugin-jsx-a11y": { - "version": "6.6.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.18.9", - "aria-query": "^4.2.2", - "array-includes": "^3.1.5", - "ast-types-flow": "^0.0.7", - "axe-core": "^4.4.3", - "axobject-query": "^2.2.0", - "damerau-levenshtein": "^1.0.8", - "emoji-regex": "^9.2.2", - "has": "^1.0.3", - "jsx-ast-utils": "^3.3.2", - "language-tags": "^1.0.5", - "minimatch": "^3.1.2", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=4.0" - }, - "peerDependencies": { - "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" - } - }, - "node_modules/eslint-plugin-jsx-a11y/node_modules/semver": { - "version": "6.3.0", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/eslint-plugin-no-only-tests": { - "version": "2.6.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/eslint-plugin-node": { - "version": "4.2.3", - "dev": true, - "license": "MIT", - "dependencies": { - "ignore": "^3.0.11", - "minimatch": "^3.0.2", - "object-assign": "^4.0.1", - "resolve": "^1.1.7", - "semver": "5.3.0" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": ">=3.1.0" - } - }, - "node_modules/eslint-plugin-node/node_modules/ignore": { - "version": "3.3.10", - "dev": true, - "license": "MIT" - }, - "node_modules/eslint-plugin-node/node_modules/semver": { - "version": "5.3.0", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/eslint-plugin-prettier": { - "version": "4.2.1", - "dev": true, - "license": "MIT", - "dependencies": { - "prettier-linter-helpers": "^1.0.0" - }, - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "eslint": ">=7.28.0", - "prettier": ">=2.0.0" - }, - "peerDependenciesMeta": { - "eslint-config-prettier": { - "optional": true - } - } - }, - "node_modules/eslint-plugin-promise": { - "version": "3.5.0", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-plugin-simple-import-sort": { - "version": "7.0.0", - "dev": true, - "license": "MIT", - "peerDependencies": { - "eslint": ">=5.0.0" - } - }, - "node_modules/eslint-plugin-sonarjs": { - "version": "0.14.0", - "dev": true, - "license": "LGPL-3.0", - "engines": { - "node": ">=12" - }, - "peerDependencies": { - "eslint": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/eslint-plugin-standard": { - "version": "3.0.1", - "dev": true, - "license": "MIT", - "peerDependencies": { - "eslint": ">=3.19.0" - } - }, - "node_modules/eslint-rule-documentation": { - "version": "1.0.23", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/eslint-scope": { - "version": "5.1.1", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/eslint-utils": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "eslint-visitor-keys": "^2.0.0" - }, - "engines": { - "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - }, - "peerDependencies": { - "eslint": ">=5" - } - }, - "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "2.1.0", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=10" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "3.3.0", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/eslint/node_modules/escape-string-regexp": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/eslint-scope": { - "version": "7.1.1", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/eslint/node_modules/estraverse": { - "version": "5.3.0", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/espree": { - "version": "9.4.0", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "acorn": "^8.8.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/esprima": { - "version": "4.0.1", - "dev": true, - "license": "BSD-2-Clause", - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/esquery": { - "version": "1.4.0", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/esquery/node_modules/estraverse": { - "version": "5.3.0", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esrecurse/node_modules/estraverse": { - "version": "5.3.0", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "4.3.0", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estree-is-member-expression": { - "version": "1.0.0", - "dev": true, - "license": "Apache-2.0" - }, - "node_modules/esutils": { - "version": "2.0.3", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ethereum-cryptography": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-2.0.0.tgz", - "integrity": "sha512-g25m4EtfQGjstWgVE1aIz7XYYjf3kH5kG17ULWVB5dH6uLahsoltOhACzSxyDV+fhn4gbR4xRrOXGe6r2uh4Bg==", - "dependencies": { - "@noble/curves": "1.0.0", - "@noble/hashes": "1.3.0", - "@scure/bip32": "1.3.0", - "@scure/bip39": "1.2.0" - } - }, - "node_modules/ethers": { - "version": "5.7.2", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "dependencies": { - "@ethersproject/abi": "5.7.0", - "@ethersproject/abstract-provider": "5.7.0", - "@ethersproject/abstract-signer": "5.7.0", - "@ethersproject/address": "5.7.0", - "@ethersproject/base64": "5.7.0", - "@ethersproject/basex": "5.7.0", - "@ethersproject/bignumber": "5.7.0", - "@ethersproject/bytes": "5.7.0", - "@ethersproject/constants": "5.7.0", - "@ethersproject/contracts": "5.7.0", - "@ethersproject/hash": "5.7.0", - "@ethersproject/hdnode": "5.7.0", - "@ethersproject/json-wallets": "5.7.0", - "@ethersproject/keccak256": "5.7.0", - "@ethersproject/logger": "5.7.0", - "@ethersproject/networks": "5.7.1", - "@ethersproject/pbkdf2": "5.7.0", - "@ethersproject/properties": "5.7.0", - "@ethersproject/providers": "5.7.2", - "@ethersproject/random": "5.7.0", - "@ethersproject/rlp": "5.7.0", - "@ethersproject/sha2": "5.7.0", - "@ethersproject/signing-key": "5.7.0", - "@ethersproject/solidity": "5.7.0", - "@ethersproject/strings": "5.7.0", - "@ethersproject/transactions": "5.7.0", - "@ethersproject/units": "5.7.0", - "@ethersproject/wallet": "5.7.0", - "@ethersproject/web": "5.7.1", - "@ethersproject/wordlists": "5.7.0" - } - }, - "node_modules/event-emitter": { - "version": "0.3.5", - "dev": true, - "license": "MIT", - "dependencies": { - "d": "1", - "es5-ext": "~0.10.14" - } - }, - "node_modules/event-iterator": { - "version": "2.0.0", - "license": "MIT" - }, - "node_modules/event-target-shim": { - "version": "5.0.1", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/eventemitter3": { - "version": "4.0.7", - "license": "MIT" - }, - "node_modules/events": { - "version": "2.1.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.4.x" - } - }, - "node_modules/evp_bytestokey": { - "version": "1.0.3", - "dev": true, - "license": "MIT", - "dependencies": { - "md5.js": "^1.3.4", - "safe-buffer": "^5.1.1" - } - }, - "node_modules/execa": { - "version": "5.1.1", - "license": "MIT", - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/execspawn": { - "version": "1.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "util-extend": "^1.0.1" - } - }, - "node_modules/exit-hook": { - "version": "1.1.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ext": { - "version": "1.7.0", - "dev": true, - "license": "ISC", - "dependencies": { - "type": "^2.7.2" - } - }, - "node_modules/ext/node_modules/type": { - "version": "2.7.2", - "dev": true, - "license": "ISC" - }, - "node_modules/extend": { - "version": "3.0.2", - "license": "MIT" - }, - "node_modules/extsprintf": { - "version": "1.3.0", - "engines": [ - "node >=0.6.0" - ], - "license": "MIT" - }, - "node_modules/eyes": { - "version": "0.1.8", - "engines": { - "node": "> 0.1.90" - } - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "license": "MIT" - }, - "node_modules/fast-diff": { - "version": "1.2.0", - "dev": true, - "license": "Apache-2.0" - }, - "node_modules/fast-fifo": { - "version": "1.1.0", - "license": "MIT" - }, - "node_modules/fast-glob": { - "version": "3.2.12", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fast-glob/node_modules/glob-parent": { - "version": "5.1.2", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "license": "MIT" - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "dev": true, - "license": "MIT" - }, - "node_modules/fast-redact": { - "version": "2.1.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/fast-safe-stringify": { - "version": "2.1.1", - "dev": true, - "license": "MIT" - }, - "node_modules/fastest-levenshtein": { - "version": "1.0.16", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4.9.1" - } - }, - "node_modules/fastq": { - "version": "1.13.0", - "dev": true, - "license": "ISC", - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/fecha": { - "version": "4.2.3", - "license": "MIT" - }, - "node_modules/figures": { - "version": "1.7.0", - "dev": true, - "license": "MIT", - "dependencies": { - "escape-string-regexp": "^1.0.5", - "object-assign": "^4.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/file-entry-cache": { - "version": "6.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "flat-cache": "^3.0.4" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/file-replace-loader": { - "version": "1.4.0", - "dev": true, - "license": "MIT", - "dependencies": { - "loader-utils": "^2.0.0", - "schema-utils": "^2.7.1" - } - }, - "node_modules/file-stream-rotator": { - "version": "0.6.1", - "license": "MIT", - "dependencies": { - "moment": "^2.29.1" - } - }, - "node_modules/file-uri-to-path": { - "version": "1.0.0", - "license": "MIT" - }, - "node_modules/fill-range": { - "version": "7.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/finalhandler": { - "version": "1.1.2", - "license": "MIT", - "dependencies": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "statuses": "~1.5.0", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/finalhandler/node_modules/debug": { - "version": "2.6.9", - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/finalhandler/node_modules/ms": { - "version": "2.0.0", - "license": "MIT" - }, - "node_modules/finalhandler/node_modules/on-finished": { - "version": "2.3.0", - "license": "MIT", - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/find-cache-dir": { - "version": "3.3.2", - "dev": true, - "license": "MIT", - "dependencies": { - "commondir": "^1.0.1", - "make-dir": "^3.0.2", - "pkg-dir": "^4.1.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/avajs/find-cache-dir?sponsor=1" - } - }, - "node_modules/find-cache-dir/node_modules/make-dir": { - "version": "3.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "semver": "^6.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/find-cache-dir/node_modules/semver": { - "version": "6.3.0", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/find-root": { - "version": "1.1.0", - "dev": true, - "license": "MIT" - }, - "node_modules/find-up": { - "version": "5.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/findup": { - "version": "0.1.5", - "dev": true, - "dependencies": { - "colors": "~0.6.0-1", - "commander": "~2.1.0" - }, - "bin": { - "findup": "bin/findup.js" - }, - "engines": { - "node": ">=0.6" - } - }, - "node_modules/flat-cache": { - "version": "3.0.4", - "dev": true, - "license": "MIT", - "dependencies": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/flatstr": { - "version": "1.0.12", - "dev": true, - "license": "MIT" - }, - "node_modules/flatted": { - "version": "3.2.7", - "dev": true, - "license": "ISC" - }, - "node_modules/fn.name": { - "version": "1.1.0", - "license": "MIT" - }, - "node_modules/follow-redirects": { - "version": "1.15.2", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "license": "MIT", - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } - }, - "node_modules/for-each": { - "version": "0.3.3", - "license": "MIT", - "dependencies": { - "is-callable": "^1.1.3" - } - }, - "node_modules/foreground-child": { - "version": "2.0.0", - "dev": true, - "license": "ISC", - "dependencies": { - "cross-spawn": "^7.0.0", - "signal-exit": "^3.0.2" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/forever-agent": { - "version": "0.6.1", - "license": "Apache-2.0", - "engines": { - "node": "*" - } - }, - "node_modules/form-data": { - "version": "2.3.3", - "license": "MIT", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 0.12" - } - }, - "node_modules/formidable": { - "version": "2.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "dezalgo": "1.0.3", - "hexoid": "1.0.0", - "once": "1.4.0", - "qs": "6.9.3" - }, - "funding": { - "url": "https://ko-fi.com/tunnckoCore/commissions" - } - }, - "node_modules/formidable/node_modules/qs": { - "version": "6.9.3", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/fromentries": { - "version": "1.3.2", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/fs-extra": { - "version": "10.1.0", - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "dev": true, - "license": "ISC" - }, - "node_modules/function-bind": { - "version": "1.1.1", - "license": "MIT" - }, - "node_modules/function.prototype.name": { - "version": "1.1.5", - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.0", - "functions-have-names": "^1.2.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/functional-red-black-tree": { - "version": "1.0.1", - "license": "MIT" - }, - "node_modules/functions-have-names": { - "version": "1.2.3", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/generate-function": { - "version": "2.3.1", - "dev": true, - "license": "MIT", - "dependencies": { - "is-property": "^1.0.2" - } - }, - "node_modules/generate-object-property": { - "version": "1.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "is-property": "^1.0.0" - } - }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/get-assigned-identifiers": { - "version": "1.2.0", - "dev": true, - "license": "Apache-2.0" - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "license": "ISC", - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/get-func-name": { - "version": "2.0.0", - "license": "MIT", - "engines": { - "node": "*" - } - }, - "node_modules/get-intrinsic": { - "version": "1.1.3", - "license": "MIT", - "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-iterator": { - "version": "1.0.2", - "license": "MIT" - }, - "node_modules/get-package-type": { - "version": "0.1.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/get-stdin": { - "version": "5.0.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/get-stream": { - "version": "6.0.1", - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/get-symbol-description": { - "version": "1.0.0", - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/getpass": { - "version": "0.1.7", - "license": "MIT", - "dependencies": { - "assert-plus": "^1.0.0" - } - }, - "node_modules/git-hooks-list": { - "version": "1.0.3", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/fisker/git-hooks-list?sponsor=1" - } - }, - "node_modules/glob": { - "version": "7.2.3", - "dev": true, - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "6.0.2", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/glob-to-regexp": { - "version": "0.4.1", - "dev": true, - "license": "BSD-2-Clause" - }, - "node_modules/globals": { - "version": "13.17.0", - "dev": true, - "license": "MIT", - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/globby": { - "version": "11.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.10", - "license": "ISC" - }, - "node_modules/grapheme-splitter": { - "version": "1.0.4", - "dev": true, - "license": "MIT" - }, - "node_modules/handlebars": { - "version": "4.7.7", - "dev": true, - "license": "MIT", - "dependencies": { - "minimist": "^1.2.5", - "neo-async": "^2.6.0", - "source-map": "^0.6.1", - "wordwrap": "^1.0.0" - }, - "bin": { - "handlebars": "bin/handlebars" - }, - "engines": { - "node": ">=0.4.7" - }, - "optionalDependencies": { - "uglify-js": "^3.1.4" - } - }, - "node_modules/handlebars/node_modules/source-map": { - "version": "0.6.1", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/har-schema": { - "version": "2.0.0", - "license": "ISC", - "engines": { - "node": ">=4" - } - }, - "node_modules/har-validator": { - "version": "5.1.5", - "license": "MIT", - "dependencies": { - "ajv": "^6.12.3", - "har-schema": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/has": { - "version": "1.0.3", - "license": "MIT", - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/has-ansi": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/has-ansi/node_modules/ansi-regex": { - "version": "2.1.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/has-bigints": { - "version": "1.0.2", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-dynamic-import": { - "version": "2.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-flag": { - "version": "4.0.0", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/has-property-descriptors": { - "version": "1.0.0", - "license": "MIT", - "dependencies": { - "get-intrinsic": "^1.1.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-symbols": { - "version": "1.0.3", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-tostringtag": { - "version": "1.0.0", - "license": "MIT", - "dependencies": { - "has-symbols": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-unicode": { - "version": "2.0.1", - "dev": true, - "license": "ISC" - }, - "node_modules/hash-base": { - "version": "3.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "inherits": "^2.0.4", - "readable-stream": "^3.6.0", - "safe-buffer": "^5.2.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/hash-base/node_modules/readable-stream": { - "version": "3.6.0", - "dev": true, - "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/hash.js": { - "version": "1.1.7", - "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.1" - } - }, - "node_modules/hasha": { - "version": "5.2.2", - "dev": true, - "license": "MIT", - "dependencies": { - "is-stream": "^2.0.0", - "type-fest": "^0.8.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/hasha/node_modules/type-fest": { - "version": "0.8.1", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=8" - } - }, - "node_modules/hashlru": { - "version": "2.3.0", - "license": "MIT" - }, - "node_modules/heap": { - "version": "0.2.7", - "license": "MIT" - }, - "node_modules/hexoid": { - "version": "1.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/hmac-drbg": { - "version": "1.0.1", - "license": "MIT", - "dependencies": { - "hash.js": "^1.0.3", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.1" - } - }, - "node_modules/hsl-to-rgb-for-reals": { - "version": "1.1.1", - "dev": true, - "license": "ISC" - }, - "node_modules/html-escaper": { - "version": "2.0.2", - "dev": true, - "license": "MIT" - }, - "node_modules/htmlescape": { - "version": "1.1.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10" - } - }, - "node_modules/http-errors": { - "version": "2.0.0", - "license": "MIT", - "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/http-errors/node_modules/statuses": { - "version": "2.0.1", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/http-proxy": { - "version": "1.18.1", - "dev": true, - "license": "MIT", - "dependencies": { - "eventemitter3": "^4.0.0", - "follow-redirects": "^1.0.0", - "requires-port": "^1.0.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/http-signature": { - "version": "1.2.0", - "license": "MIT", - "dependencies": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - }, - "engines": { - "node": ">=0.8", - "npm": ">=1.3.7" - } - }, - "node_modules/https-browserify": { - "version": "1.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/human-signals": { - "version": "2.1.0", - "license": "Apache-2.0", - "engines": { - "node": ">=10.17.0" - } - }, - "node_modules/hyperscript-attribute-to-property": { - "version": "1.0.2", - "dev": true, - "license": "MIT" - }, - "node_modules/hyperx": { - "version": "2.5.4", - "dev": true, - "license": "BSD", - "dependencies": { - "hyperscript-attribute-to-property": "^1.0.0" - } - }, - "node_modules/iconv-lite": { - "version": "0.4.24", - "license": "MIT", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ieee754": { - "version": "1.2.1", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "BSD-3-Clause" - }, - "node_modules/ignore": { - "version": "5.2.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/import-fresh": { - "version": "3.3.0", - "dev": true, - "license": "MIT", - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/import-local": { - "version": "3.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" - }, - "bin": { - "import-local-fixture": "fixtures/cli.js" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/indent-string": { - "version": "4.0.0", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "dev": true, - "license": "ISC", - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "license": "ISC" - }, - "node_modules/inline-source-map": { - "version": "0.6.2", - "dev": true, - "license": "MIT", - "dependencies": { - "source-map": "~0.5.3" - } - }, - "node_modules/inquirer": { - "version": "0.12.0", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-escapes": "^1.1.0", - "ansi-regex": "^2.0.0", - "chalk": "^1.0.0", - "cli-cursor": "^1.0.1", - "cli-width": "^2.0.0", - "figures": "^1.3.5", - "lodash": "^4.3.0", - "readline2": "^1.0.1", - "run-async": "^0.1.0", - "rx-lite": "^3.1.2", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.0", - "through": "^2.3.6" - } - }, - "node_modules/inquirer/node_modules/ansi-escapes": { - "version": "1.4.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/inquirer/node_modules/ansi-regex": { - "version": "2.1.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/inquirer/node_modules/ansi-styles": { - "version": "2.2.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/inquirer/node_modules/chalk": { - "version": "1.1.3", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/inquirer/node_modules/cli-cursor": { - "version": "1.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "restore-cursor": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/inquirer/node_modules/is-fullwidth-code-point": { - "version": "1.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "number-is-nan": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/inquirer/node_modules/onetime": { - "version": "1.1.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/inquirer/node_modules/restore-cursor": { - "version": "1.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "exit-hook": "^1.0.0", - "onetime": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/inquirer/node_modules/string-width": { - "version": "1.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/inquirer/node_modules/strip-ansi": { - "version": "3.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/inquirer/node_modules/supports-color": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/insert-module-globals": { - "version": "7.2.1", - "dev": true, - "license": "MIT", - "dependencies": { - "acorn-node": "^1.5.2", - "combine-source-map": "^0.8.0", - "concat-stream": "^1.6.1", - "is-buffer": "^1.1.0", - "JSONStream": "^1.0.3", - "path-is-absolute": "^1.0.1", - "process": "~0.11.0", - "through2": "^2.0.0", - "undeclared-identifiers": "^1.1.2", - "xtend": "^4.0.0" - }, - "bin": { - "insert-module-globals": "bin/cmd.js" - } - }, - "node_modules/insert-module-globals/node_modules/is-buffer": { - "version": "1.1.6", - "dev": true, - "license": "MIT" - }, - "node_modules/interface-datastore": { - "version": "3.0.6", - "license": "MIT", - "dependencies": { - "err-code": "^3.0.1", - "ipfs-utils": "^6.0.0", - "iso-random-stream": "^2.0.0", - "it-all": "^1.0.2", - "it-drain": "^1.0.1", - "nanoid": "^3.0.2" - } - }, - "node_modules/interface-datastore/node_modules/err-code": { - "version": "3.0.1", - "license": "MIT" - }, - "node_modules/internal-slot": { - "version": "1.0.3", - "license": "MIT", - "dependencies": { - "get-intrinsic": "^1.1.0", - "has": "^1.0.3", - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/internmap": { - "version": "1.0.1", - "dev": true, - "license": "ISC" - }, - "node_modules/interpret": { - "version": "2.2.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/ip-address": { - "version": "6.4.0", - "license": "MIT", - "dependencies": { - "jsbn": "1.1.0", - "lodash.find": "4.6.0", - "lodash.max": "4.0.1", - "lodash.merge": "4.6.2", - "lodash.padstart": "4.6.1", - "lodash.repeat": "4.1.0", - "sprintf-js": "1.1.2" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/ip-regex": { - "version": "4.3.0", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/ipaddr.js": { - "version": "2.0.1", - "license": "MIT", - "engines": { - "node": ">= 10" - } - }, - "node_modules/ipfs-utils": { - "version": "6.0.8", - "license": "MIT", - "dependencies": { - "abort-controller": "^3.0.0", - "any-signal": "^2.1.0", - "buffer": "^6.0.1", - "electron-fetch": "^1.7.2", - "err-code": "^3.0.1", - "is-electron": "^2.2.0", - "iso-url": "^1.0.0", - "it-glob": "~0.0.11", - "it-to-stream": "^1.0.0", - "merge-options": "^3.0.4", - "nanoid": "^3.1.20", - "native-abort-controller": "^1.0.3", - "native-fetch": "^3.0.0", - "node-fetch": "^2.6.1", - "stream-to-it": "^0.2.2" - } - }, - "node_modules/ipfs-utils/node_modules/err-code": { - "version": "3.0.1", - "license": "MIT" - }, - "node_modules/is-arguments": { - "version": "1.1.1", - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "dev": true, - "license": "MIT" - }, - "node_modules/is-bigint": { - "version": "1.0.4", - "license": "MIT", - "dependencies": { - "has-bigints": "^1.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-boolean-attribute": { - "version": "0.0.1", - "dev": true, - "license": "MIT" - }, - "node_modules/is-boolean-object": { - "version": "1.1.2", - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-buffer": { - "version": "2.0.5", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/is-callable": { - "version": "1.2.7", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-core-module": { - "version": "2.11.0", - "dev": true, - "license": "MIT", - "dependencies": { - "has": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-date-object": { - "version": "1.0.5", - "license": "MIT", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-docker": { - "version": "2.2.1", - "dev": true, - "license": "MIT", - "bin": { - "is-docker": "cli.js" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-electron": { - "version": "2.2.1", - "license": "MIT" - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-fn": { - "version": "1.0.0", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-generator-function": { - "version": "1.0.10", - "license": "MIT", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "dev": true, - "license": "MIT", - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-ip": { - "version": "3.1.0", - "license": "MIT", - "dependencies": { - "ip-regex": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-loopback-addr": { - "version": "1.0.1", - "license": "MIT" - }, - "node_modules/is-map": { - "version": "2.0.2", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-my-ip-valid": { - "version": "1.0.1", - "dev": true, - "license": "MIT" - }, - "node_modules/is-my-json-valid": { - "version": "2.20.6", - "dev": true, - "license": "MIT", - "dependencies": { - "generate-function": "^2.0.0", - "generate-object-property": "^1.1.0", - "is-my-ip-valid": "^1.0.0", - "jsonpointer": "^5.0.0", - "xtend": "^4.0.0" - } - }, - "node_modules/is-nan": { - "version": "1.3.2", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-negative-zero": { - "version": "2.0.2", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-number-object": { - "version": "1.0.7", - "license": "MIT", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-plain-obj": { - "version": "2.1.0", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-plain-object": { - "version": "2.0.4", - "dev": true, - "license": "MIT", - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-property": { - "version": "1.0.2", - "dev": true, - "license": "MIT" - }, - "node_modules/is-regex": { - "version": "1.1.4", - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-regexp": { - "version": "1.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-resolvable": { - "version": "1.1.0", - "dev": true, - "license": "ISC" - }, - "node_modules/is-set": { - "version": "2.0.2", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-shared-array-buffer": { - "version": "1.0.2", - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-stream": { - "version": "2.0.1", - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-string": { - "version": "1.0.7", - "license": "MIT", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-symbol": { - "version": "1.0.4", - "license": "MIT", - "dependencies": { - "has-symbols": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-typed-array": { - "version": "1.1.9", - "license": "MIT", - "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "es-abstract": "^1.20.0", - "for-each": "^0.3.3", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-typedarray": { - "version": "1.0.0", - "license": "MIT" - }, - "node_modules/is-weakmap": { - "version": "2.0.1", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-weakref": { - "version": "1.0.2", - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-weakset": { - "version": "2.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-windows": { - "version": "1.0.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-wsl": { - "version": "2.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "is-docker": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/isarray": { - "version": "1.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/isbinaryfile": { - "version": "4.0.10", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/gjtorikian/" - } - }, - "node_modules/isexe": { - "version": "2.0.0", - "license": "ISC" - }, - "node_modules/iso-random-stream": { - "version": "2.0.2", - "license": "MIT", - "dependencies": { - "events": "^3.3.0", - "readable-stream": "^3.4.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/iso-random-stream/node_modules/events": { - "version": "3.3.0", - "license": "MIT", - "engines": { - "node": ">=0.8.x" - } - }, - "node_modules/iso-random-stream/node_modules/readable-stream": { - "version": "3.6.0", - "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/iso-url": { - "version": "1.2.1", - "license": "MIT", - "engines": { - "node": ">=12" - } - }, - "node_modules/isobject": { - "version": "3.0.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/isomorphic-ws": { - "version": "4.0.1", - "license": "MIT", - "peerDependencies": { - "ws": "*" - } - }, - "node_modules/isstream": { - "version": "0.1.2", - "license": "MIT" - }, - "node_modules/istanbul-lib-coverage": { - "version": "3.2.0", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-hook": { - "version": "3.0.0", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "append-transform": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-instrument": { - "version": "4.0.3", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@babel/core": "^7.7.5", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.0.0", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-instrument/node_modules/semver": { - "version": "6.3.0", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/istanbul-lib-processinfo": { - "version": "2.0.3", - "dev": true, - "license": "ISC", - "dependencies": { - "archy": "^1.0.0", - "cross-spawn": "^7.0.3", - "istanbul-lib-coverage": "^3.2.0", - "p-map": "^3.0.0", - "rimraf": "^3.0.0", - "uuid": "^8.3.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-processinfo/node_modules/p-map": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "aggregate-error": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-report": { - "version": "3.0.0", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^3.0.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-report/node_modules/make-dir": { - "version": "3.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "semver": "^6.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/istanbul-lib-report/node_modules/semver": { - "version": "6.3.0", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/istanbul-lib-source-maps": { - "version": "4.0.1", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/istanbul-lib-source-maps/node_modules/source-map": { - "version": "0.6.1", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/istanbul-reports": { - "version": "3.1.5", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/it-all": { - "version": "1.0.6", - "license": "ISC" - }, - "node_modules/it-buffer": { - "version": "0.1.3", - "license": "MPL-2.0", - "dependencies": { - "bl": "^5.0.0", - "buffer": "^6.0.3" - } - }, - "node_modules/it-buffer/node_modules/bl": { - "version": "5.1.0", - "license": "MIT", - "dependencies": { - "buffer": "^6.0.3", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - } - }, - "node_modules/it-buffer/node_modules/readable-stream": { - "version": "3.6.0", - "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/it-drain": { - "version": "1.0.5", - "license": "ISC" - }, - "node_modules/it-filter": { - "version": "1.0.3", - "license": "ISC" - }, - "node_modules/it-first": { - "version": "1.0.7", - "license": "ISC" - }, - "node_modules/it-glob": { - "version": "0.0.14", - "license": "ISC", - "dependencies": { - "@types/minimatch": "^3.0.4", - "minimatch": "^3.0.4" - } - }, - "node_modules/it-goodbye": { - "version": "2.0.2", - "license": "MIT", - "dependencies": { - "buffer": "^5.6.0" - } - }, - "node_modules/it-goodbye/node_modules/buffer": { - "version": "5.7.1", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, - "node_modules/it-handshake": { - "version": "2.0.0", - "license": "MIT", - "dependencies": { - "it-pushable": "^1.4.0", - "it-reader": "^3.0.0", - "p-defer": "^3.0.0" - } - }, - "node_modules/it-length-prefixed": { - "version": "5.0.3", - "license": "MIT", - "dependencies": { - "bl": "^5.0.0", - "buffer": "^6.0.3", - "varint": "^6.0.0" - } - }, - "node_modules/it-length-prefixed/node_modules/bl": { - "version": "5.1.0", - "license": "MIT", - "dependencies": { - "buffer": "^6.0.3", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - } - }, - "node_modules/it-length-prefixed/node_modules/readable-stream": { - "version": "3.6.0", - "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/it-map": { - "version": "1.0.6", - "license": "ISC" - }, - "node_modules/it-merge": { - "version": "1.0.0", - "license": "ISC", - "dependencies": { - "it-pushable": "^1.4.0" - } - }, - "node_modules/it-pair": { - "version": "1.0.0", - "license": "MIT", - "dependencies": { - "get-iterator": "^1.0.2" - } - }, - "node_modules/it-pb-rpc": { - "version": "0.1.13", - "license": "MPL-2.0", - "dependencies": { - "is-buffer": "^2.0.5", - "it-handshake": "^2.0.0", - "it-length-prefixed": "^5.0.2" - } - }, - "node_modules/it-pipe": { - "version": "1.1.0", - "license": "MIT" - }, - "node_modules/it-protocol-buffers": { - "version": "0.2.1", - "license": "MIT", - "dependencies": { - "it-buffer": "^0.1.1", - "it-length-prefixed": "^3.0.0" - } - }, - "node_modules/it-protocol-buffers/node_modules/bl": { - "version": "4.1.0", - "license": "MIT", - "dependencies": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - } - }, - "node_modules/it-protocol-buffers/node_modules/buffer": { - "version": "5.7.1", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, - "node_modules/it-protocol-buffers/node_modules/it-length-prefixed": { - "version": "3.1.0", - "license": "MIT", - "dependencies": { - "@types/bl": "^2.1.0", - "bl": "^4.0.2", - "buffer": "^5.5.0", - "varint": "^5.0.0" - } - }, - "node_modules/it-protocol-buffers/node_modules/readable-stream": { - "version": "3.6.0", - "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/it-protocol-buffers/node_modules/varint": { - "version": "5.0.2", - "license": "MIT" - }, - "node_modules/it-pushable": { - "version": "1.4.2", - "license": "MIT", - "dependencies": { - "fast-fifo": "^1.0.0" - } - }, - "node_modules/it-reader": { - "version": "3.0.0", - "license": "MIT", - "dependencies": { - "bl": "^5.0.0" - } - }, - "node_modules/it-reader/node_modules/bl": { - "version": "5.1.0", - "license": "MIT", - "dependencies": { - "buffer": "^6.0.3", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - } - }, - "node_modules/it-reader/node_modules/readable-stream": { - "version": "3.6.0", - "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/it-take": { - "version": "1.0.0", - "license": "ISC" - }, - "node_modules/it-to-stream": { - "version": "1.0.0", - "license": "MIT", - "dependencies": { - "buffer": "^6.0.3", - "fast-fifo": "^1.0.0", - "get-iterator": "^1.0.2", - "p-defer": "^3.0.0", - "p-fifo": "^1.0.0", - "readable-stream": "^3.6.0" - } - }, - "node_modules/it-to-stream/node_modules/readable-stream": { - "version": "3.6.0", - "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/it-ws": { - "version": "4.0.0", - "license": "MIT", - "dependencies": { - "buffer": "^6.0.3", - "event-iterator": "^2.0.0", - "iso-url": "^1.1.2", - "ws": "^7.3.1" - } - }, - "node_modules/jayson": { - "version": "4.0.0", - "license": "MIT", - "dependencies": { - "@types/connect": "^3.4.33", - "@types/node": "^12.12.54", - "@types/ws": "^7.4.4", - "commander": "^2.20.3", - "delay": "^5.0.0", - "es6-promisify": "^5.0.0", - "eyes": "^0.1.8", - "isomorphic-ws": "^4.0.1", - "json-stringify-safe": "^5.0.1", - "JSONStream": "^1.3.5", - "uuid": "^8.3.2", - "ws": "^7.4.5" - }, - "bin": { - "jayson": "bin/jayson.js" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jayson/node_modules/@types/node": { - "version": "12.20.55", - "license": "MIT" - }, - "node_modules/jayson/node_modules/commander": { - "version": "2.20.3", - "license": "MIT" - }, - "node_modules/jest-worker": { - "version": "27.5.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "engines": { - "node": ">= 10.13.0" - } - }, - "node_modules/jest-worker/node_modules/supports-color": { - "version": "8.1.1", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/js-sdsl": { - "version": "4.1.5", - "license": "MIT" - }, - "node_modules/js-sha3": { - "version": "0.8.0", - "license": "MIT" - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/js-yaml": { - "version": "4.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/jsbn": { - "version": "1.1.0", - "license": "MIT" - }, - "node_modules/jsesc": { - "version": "2.5.2", - "dev": true, - "license": "MIT", - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/json-parse-better-errors": { - "version": "1.0.2", - "dev": true, - "license": "MIT" - }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "dev": true, - "license": "MIT" - }, - "node_modules/json-schema": { - "version": "0.4.0", - "license": "(AFL-2.1 OR BSD-3-Clause)" - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "license": "MIT" - }, - "node_modules/json-stable-stringify": { - "version": "0.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "jsonify": "~0.0.0" - } - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "dev": true, - "license": "MIT" - }, - "node_modules/json-stringify-safe": { - "version": "5.0.1", - "license": "ISC" - }, - "node_modules/json5": { - "version": "2.2.1", - "dev": true, - "license": "MIT", - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/jsonc-parser": { - "version": "3.2.0", - "dev": true, - "license": "MIT" - }, - "node_modules/jsonfile": { - "version": "6.1.0", - "license": "MIT", - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/jsonify": { - "version": "0.0.1", - "dev": true, - "license": "Public Domain", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/jsonparse": { - "version": "1.3.1", - "engines": [ - "node >= 0.2.0" - ], - "license": "MIT" - }, - "node_modules/jsonpointer": { - "version": "5.0.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/JSONStream": { - "version": "1.3.5", - "license": "(MIT OR Apache-2.0)", - "dependencies": { - "jsonparse": "^1.2.0", - "through": ">=2.2.7 <3" - }, - "bin": { - "JSONStream": "bin.js" - }, - "engines": { - "node": "*" - } - }, - "node_modules/jsonstream2": { - "version": "1.1.2", - "dev": true, - "license": "MIT", - "dependencies": { - "jsonparse": "0.0.6", - "through2": "^0.6.1", - "type-component": "0.0.1" - }, - "bin": { - "jsonstream": "bin/jsonstream.js" - } - }, - "node_modules/jsonstream2/node_modules/isarray": { - "version": "0.0.1", - "dev": true, - "license": "MIT" - }, - "node_modules/jsonstream2/node_modules/jsonparse": { - "version": "0.0.6", - "dev": true, - "engines": [ - "node >= 0.2.0" - ], - "license": "MIT" - }, - "node_modules/jsonstream2/node_modules/readable-stream": { - "version": "1.0.34", - "dev": true, - "license": "MIT", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "node_modules/jsonstream2/node_modules/string_decoder": { - "version": "0.10.31", - "dev": true, - "license": "MIT" - }, - "node_modules/jsonstream2/node_modules/through2": { - "version": "0.6.5", - "dev": true, - "license": "MIT", - "dependencies": { - "readable-stream": ">=1.0.33-1 <1.1.0-0", - "xtend": ">=4.0.0 <4.1.0-0" - } - }, - "node_modules/jsprim": { - "version": "1.4.2", - "license": "MIT", - "dependencies": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.4.0", - "verror": "1.10.0" - }, - "engines": { - "node": ">=0.6.0" - } - }, - "node_modules/jsx-ast-utils": { - "version": "3.3.3", - "dev": true, - "license": "MIT", - "dependencies": { - "array-includes": "^3.1.5", - "object.assign": "^4.1.3" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/just-extend": { - "version": "4.2.1", - "license": "MIT" - }, - "node_modules/jwt-simple": { - "version": "0.5.6", - "license": "MIT", - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/k-bucket": { - "version": "5.1.0", - "license": "MIT", - "dependencies": { - "randombytes": "^2.1.0" - } - }, - "node_modules/karma": { - "version": "6.4.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@colors/colors": "1.5.0", - "body-parser": "^1.19.0", - "braces": "^3.0.2", - "chokidar": "^3.5.1", - "connect": "^3.7.0", - "di": "^0.0.1", - "dom-serialize": "^2.2.1", - "glob": "^7.1.7", - "graceful-fs": "^4.2.6", - "http-proxy": "^1.18.1", - "isbinaryfile": "^4.0.8", - "lodash": "^4.17.21", - "log4js": "^6.4.1", - "mime": "^2.5.2", - "minimatch": "^3.0.4", - "mkdirp": "^0.5.5", - "qjobs": "^1.2.0", - "range-parser": "^1.2.1", - "rimraf": "^3.0.2", - "socket.io": "^4.4.1", - "source-map": "^0.6.1", - "tmp": "^0.2.1", - "ua-parser-js": "^0.7.30", - "yargs": "^16.1.1" - }, - "bin": { - "karma": "bin/karma" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/karma-chrome-launcher": { - "version": "3.1.1", - "dev": true, - "license": "MIT", - "dependencies": { - "which": "^1.2.1" - } - }, - "node_modules/karma-firefox-launcher": { - "version": "2.1.2", - "dev": true, - "license": "MIT", - "dependencies": { - "is-wsl": "^2.2.0", - "which": "^2.0.1" - } - }, - "node_modules/karma-firefox-launcher/node_modules/which": { - "version": "2.0.2", - "dev": true, - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/karma-tap": { - "version": "4.2.0", - "dev": true, - "license": "ISC", - "dependencies": { - "babel-polyfill": "^6.26.0" - }, - "peerDependencies": { - "karma": ">=1.0.0" - } - }, - "node_modules/karma-typescript": { - "version": "5.5.3", - "dev": true, - "license": "MIT", - "dependencies": { - "acorn": "^8.1.0", - "acorn-walk": "^8.0.2", - "assert": "^2.0.0", - "async": "^3.0.1", - "browser-resolve": "^2.0.0", - "browserify-zlib": "^0.2.0", - "buffer": "^5.4.3", - "combine-source-map": "^0.8.0", - "console-browserify": "^1.2.0", - "constants-browserify": "^1.0.0", - "convert-source-map": "^1.7.0", - "crypto-browserify": "^3.12.0", - "diff": "^4.0.1", - "domain-browser": "^4.16.0", - "events": "^3.2.0", - "glob": "^7.1.6", - "https-browserify": "^1.0.0", - "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-instrument": "^4.0.0", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^4.0.0", - "istanbul-reports": "^3.0.0", - "json-stringify-safe": "^5.0.1", - "lodash": "^4.17.19", - "log4js": "^6.3.0", - "minimatch": "^3.0.4", - "os-browserify": "^0.3.0", - "pad": "^3.2.0", - "path-browserify": "^1.0.0", - "process": "^0.11.10", - "punycode": "^2.1.1", - "querystring-es3": "^0.2.1", - "readable-stream": "^3.1.1", - "source-map": "^0.7.3", - "stream-browserify": "^3.0.0", - "stream-http": "^3.1.0", - "string_decoder": "^1.3.0", - "timers-browserify": "^2.0.11", - "tmp": "^0.2.1", - "tty-browserify": "^0.0.1", - "url": "^0.11.0", - "util": "^0.12.1", - "vm-browserify": "^1.1.2" - }, - "peerDependencies": { - "karma": "1 || 2 || 3 || 4 || 5 || 6", - "typescript": "1 || 2 || 3 || 4" - } - }, - "node_modules/karma-typescript-es6-transform": { - "version": "5.5.3", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/core": "^7.11.1", - "@babel/preset-env": "^7.11.0", - "acorn": "^8.1.0", - "acorn-walk": "^8.0.2", - "log4js": "^6.3.0", - "magic-string": "^0.25.7" - } - }, - "node_modules/karma-typescript-es6-transform/node_modules/acorn-walk": { - "version": "8.2.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/karma-typescript/node_modules/acorn-walk": { - "version": "8.2.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/karma-typescript/node_modules/assert": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "es6-object-assign": "^1.1.0", - "is-nan": "^1.2.1", - "object-is": "^1.0.1", - "util": "^0.12.0" - } - }, - "node_modules/karma-typescript/node_modules/buffer": { - "version": "5.7.1", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, - "node_modules/karma-typescript/node_modules/convert-source-map": { - "version": "1.9.0", - "dev": true, - "license": "MIT" - }, - "node_modules/karma-typescript/node_modules/domain-browser": { - "version": "4.22.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://bevry.me/fund" - } - }, - "node_modules/karma-typescript/node_modules/events": { - "version": "3.3.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.x" - } - }, - "node_modules/karma-typescript/node_modules/path-browserify": { - "version": "1.0.1", - "dev": true, - "license": "MIT" - }, - "node_modules/karma-typescript/node_modules/punycode": { - "version": "2.1.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/karma-typescript/node_modules/readable-stream": { - "version": "3.6.0", - "dev": true, - "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/karma-typescript/node_modules/source-map": { - "version": "0.7.4", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">= 8" - } - }, - "node_modules/karma-typescript/node_modules/timers-browserify": { - "version": "2.0.12", - "dev": true, - "license": "MIT", - "dependencies": { - "setimmediate": "^1.0.4" - }, - "engines": { - "node": ">=0.6.0" - } - }, - "node_modules/karma/node_modules/source-map": { - "version": "0.6.1", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/keypair": { - "version": "1.0.4", - "license": "BSD / GPL" - }, - "node_modules/kind-of": { - "version": "6.0.3", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/kuler": { - "version": "2.0.0", - "license": "MIT" - }, - "node_modules/labeled-stream-splicer": { - "version": "2.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "inherits": "^2.0.1", - "stream-splicer": "^2.0.0" - } - }, - "node_modules/language-subtag-registry": { - "version": "0.3.22", - "dev": true, - "license": "CC0-1.0" - }, - "node_modules/language-tags": { - "version": "1.0.5", - "dev": true, - "license": "MIT", - "dependencies": { - "language-subtag-registry": "~0.3.2" - } - }, - "node_modules/level": { - "version": "8.0.0", - "license": "MIT", - "dependencies": { - "browser-level": "^1.0.1", - "classic-level": "^1.2.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/level" - } - }, - "node_modules/level-codec": { - "version": "10.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "buffer": "^6.0.3" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/level-concat-iterator": { - "version": "3.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "catering": "^2.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/level-errors": { - "version": "3.0.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - } - }, - "node_modules/level-iterator-stream": { - "version": "5.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/level-iterator-stream/node_modules/readable-stream": { - "version": "3.6.0", - "dev": true, - "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/level-js": { - "version": "6.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "abstract-leveldown": "^7.2.0", - "buffer": "^6.0.3", - "inherits": "^2.0.3", - "ltgt": "^2.1.2", - "run-parallel-limit": "^1.1.0" - } - }, - "node_modules/level-legacy": { - "name": "level", - "version": "7.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "level-js": "^6.1.0", - "level-packager": "^6.0.1", - "leveldown": "^6.1.0" - }, - "engines": { - "node": ">=10.12.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/level" - } - }, - "node_modules/level-mem": { - "version": "6.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "level-packager": "^6.0.1", - "memdown": "^6.1.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/level-packager": { - "version": "6.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "encoding-down": "^7.1.0", - "levelup": "^5.1.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/level-supports": { - "version": "4.0.1", - "license": "MIT", - "engines": { - "node": ">=12" - } - }, - "node_modules/level-transcoder": { - "version": "1.0.1", - "license": "MIT", - "dependencies": { - "buffer": "^6.0.3", - "module-error": "^1.0.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/leveldown": { - "version": "6.1.1", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "dependencies": { - "abstract-leveldown": "^7.2.0", - "napi-macros": "~2.0.0", - "node-gyp-build": "^4.3.0" - }, - "engines": { - "node": ">=10.12.0" - } - }, - "node_modules/levelup": { - "version": "5.1.1", - "dev": true, - "license": "MIT", - "dependencies": { - "catering": "^2.0.0", - "deferred-leveldown": "^7.0.0", - "level-errors": "^3.0.1", - "level-iterator-stream": "^5.0.0", - "level-supports": "^2.0.1", - "queue-microtask": "^1.2.3" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/levelup/node_modules/level-supports": { - "version": "2.1.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - } - }, - "node_modules/levn": { - "version": "0.4.1", - "dev": true, - "license": "MIT", - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/libp2p": { - "version": "0.30.13", - "license": "MIT", - "dependencies": { - "@motrix/nat-api": "^0.3.1", - "abort-controller": "^3.0.0", - "aggregate-error": "^3.1.0", - "any-signal": "^2.1.1", - "bignumber.js": "^9.0.1", - "cids": "^1.1.5", - "class-is": "^1.1.0", - "debug": "^4.3.1", - "err-code": "^2.0.0", - "es6-promisify": "^6.1.1", - "events": "^3.2.0", - "hashlru": "^2.3.0", - "interface-datastore": "^3.0.3", - "ipfs-utils": "^6.0.0", - "it-all": "^1.0.4", - "it-buffer": "^0.1.2", - "it-drain": "^1.0.3", - "it-filter": "^1.0.1", - "it-first": "^1.0.4", - "it-handshake": "^1.0.2", - "it-length-prefixed": "^3.1.0", - "it-map": "^1.0.4", - "it-merge": "1.0.0", - "it-pipe": "^1.1.0", - "it-protocol-buffers": "^0.2.0", - "it-take": "1.0.0", - "libp2p-crypto": "^0.19.0", - "libp2p-interfaces": "^0.8.1", - "libp2p-utils": "^0.2.2", - "mafmt": "^8.0.0", - "merge-options": "^3.0.4", - "moving-average": "^1.0.0", - "multiaddr": "^8.1.0", - "multicodec": "^2.1.0", - "multihashing-async": "^2.0.1", - "multistream-select": "^1.0.0", - "mutable-proxy": "^1.0.0", - "node-forge": "^0.10.0", - "p-any": "^3.0.0", - "p-fifo": "^1.0.0", - "p-retry": "^4.2.0", - "p-settle": "^4.0.1", - "peer-id": "^0.14.2", - "private-ip": "^2.0.0", - "protons": "^2.0.0", - "retimer": "^2.0.0", - "sanitize-filename": "^1.6.3", - "set-delayed-interval": "^1.0.0", - "streaming-iterables": "^5.0.2", - "timeout-abort-controller": "^1.1.1", - "uint8arrays": "^2.1.3", - "varint": "^6.0.0", - "xsalsa20": "^1.0.2" - }, - "engines": { - "node": ">=12.0.0", - "npm": ">=6.0.0" - } - }, - "node_modules/libp2p-bootstrap": { - "version": "0.14.0", - "license": "MIT", - "dependencies": { - "debug": "^4.3.1", - "mafmt": "^10.0.0", - "multiaddr": "^10.0.0", - "peer-id": "^0.16.0" - }, - "engines": { - "node": ">=15.0.0" - } - }, - "node_modules/libp2p-bootstrap/node_modules/err-code": { - "version": "3.0.1", - "license": "MIT" - }, - "node_modules/libp2p-bootstrap/node_modules/libp2p-crypto": { - "version": "0.21.2", - "license": "MIT", - "dependencies": { - "@noble/ed25519": "^1.5.1", - "@noble/secp256k1": "^1.3.0", - "err-code": "^3.0.1", - "iso-random-stream": "^2.0.0", - "multiformats": "^9.4.5", - "node-forge": "^1.2.1", - "protobufjs": "^6.11.2", - "uint8arrays": "^3.0.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/libp2p-bootstrap/node_modules/mafmt": { - "version": "10.0.0", - "license": "MIT", - "dependencies": { - "multiaddr": "^10.0.0" - } - }, - "node_modules/libp2p-bootstrap/node_modules/node-forge": { - "version": "1.3.1", - "license": "(BSD-3-Clause OR GPL-2.0)", - "engines": { - "node": ">= 6.13.0" - } - }, - "node_modules/libp2p-bootstrap/node_modules/peer-id": { - "version": "0.16.0", - "license": "MIT", - "dependencies": { - "class-is": "^1.1.0", - "libp2p-crypto": "^0.21.0", - "multiformats": "^9.4.5", - "protobufjs": "^6.10.2", - "uint8arrays": "^3.0.0" - }, - "engines": { - "node": ">=15.0.0" - } - }, - "node_modules/libp2p-crypto": { - "version": "0.19.7", - "license": "MIT", - "dependencies": { - "err-code": "^3.0.1", - "is-typedarray": "^1.0.0", - "iso-random-stream": "^2.0.0", - "keypair": "^1.0.1", - "multiformats": "^9.4.5", - "node-forge": "^0.10.0", - "pem-jwk": "^2.0.0", - "protobufjs": "^6.11.2", - "secp256k1": "^4.0.0", - "uint8arrays": "^3.0.0", - "ursa-optional": "^0.10.1" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/libp2p-crypto/node_modules/err-code": { - "version": "3.0.1", - "license": "MIT" - }, - "node_modules/libp2p-interfaces": { - "version": "1.3.1", - "license": "MIT", - "dependencies": { - "abort-controller": "^3.0.0", - "abortable-iterator": "^3.0.0", - "debug": "^4.3.1", - "err-code": "^3.0.1", - "it-length-prefixed": "^5.0.2", - "it-pipe": "^1.1.0", - "it-pushable": "^1.4.2", - "libp2p-crypto": "^0.20.0", - "multiaddr": "^10.0.0", - "multiformats": "^9.1.2", - "p-queue": "^6.6.2", - "peer-id": "^0.15.4", - "protobufjs": "^6.10.2", - "uint8arrays": "^3.0.0" - } - }, - "node_modules/libp2p-interfaces/node_modules/err-code": { - "version": "3.0.1", - "license": "MIT" - }, - "node_modules/libp2p-interfaces/node_modules/libp2p-crypto": { - "version": "0.20.0", - "license": "MIT", - "dependencies": { - "err-code": "^3.0.1", - "iso-random-stream": "^2.0.0", - "keypair": "^1.0.4", - "multiformats": "^9.4.5", - "noble-ed25519": "^1.2.6", - "noble-secp256k1": "^1.2.10", - "node-forge": "^0.10.0", - "pem-jwk": "^2.0.0", - "protobufjs": "^6.11.2", - "uint8arrays": "^3.0.0", - "ursa-optional": "^0.10.1" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/libp2p-interfaces/node_modules/peer-id": { - "version": "0.15.4", - "license": "MIT", - "dependencies": { - "class-is": "^1.1.0", - "libp2p-crypto": "^0.20.0", - "minimist": "^1.2.5", - "multiformats": "^9.4.5", - "protobufjs": "^6.10.2", - "uint8arrays": "^3.0.0" - }, - "bin": { - "peer-id": "src/bin.js" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/libp2p-kad-dht": { - "version": "0.20.6", - "license": "MIT", - "dependencies": { - "abort-controller": "^3.0.0", - "async": "^2.6.2", - "base32.js": "~0.1.0", - "cids": "^1.1.5", - "debug": "^4.3.1", - "err-code": "^2.0.3", - "hashlru": "^2.3.0", - "heap": "~0.2.6", - "interface-datastore": "^3.0.3", - "it-length-prefixed": "^3.1.0", - "it-pipe": "^1.1.0", - "k-bucket": "^5.0.0", - "libp2p-crypto": "^0.19.0", - "libp2p-interfaces": "^0.8.2", - "libp2p-record": "^0.9.0", - "multiaddr": "^8.1.2", - "multihashing-async": "^2.0.1", - "p-filter": "^2.1.0", - "p-map": "^4.0.0", - "p-queue": "^6.6.2", - "p-timeout": "^4.1.0", - "p-times": "^3.0.0", - "peer-id": "^0.14.2", - "promise-to-callback": "^1.0.0", - "protons": "^2.0.0", - "streaming-iterables": "^5.0.4", - "uint8arrays": "^2.0.5", - "varint": "^5.0.0", - "xor-distance": "^2.0.0" - }, - "engines": { - "node": ">=12.0.0", - "npm": ">=6.0.0" - } - }, - "node_modules/libp2p-kad-dht/node_modules/async": { - "version": "2.6.4", - "license": "MIT", - "dependencies": { - "lodash": "^4.17.14" - } - }, - "node_modules/libp2p-kad-dht/node_modules/bl": { - "version": "4.1.0", - "license": "MIT", - "dependencies": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - } - }, - "node_modules/libp2p-kad-dht/node_modules/buffer": { - "version": "5.7.1", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, - "node_modules/libp2p-kad-dht/node_modules/delay": { - "version": "4.4.1", - "license": "MIT", - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/libp2p-kad-dht/node_modules/it-length-prefixed": { - "version": "3.1.0", - "license": "MIT", - "dependencies": { - "@types/bl": "^2.1.0", - "bl": "^4.0.2", - "buffer": "^5.5.0", - "varint": "^5.0.0" - } - }, - "node_modules/libp2p-kad-dht/node_modules/libp2p-interfaces": { - "version": "0.8.4", - "license": "MIT", - "dependencies": { - "@types/bl": "^2.1.0", - "abort-controller": "^3.0.0", - "abortable-iterator": "^3.0.0", - "chai": "^4.2.0", - "chai-checkmark": "^1.0.1", - "debug": "^4.3.1", - "delay": "^4.4.0", - "detect-node": "^2.0.4", - "dirty-chai": "^2.0.1", - "err-code": "^2.0.3", - "it-goodbye": "^2.0.2", - "it-length-prefixed": "^3.1.0", - "it-pair": "^1.0.0", - "it-pipe": "^1.1.0", - "it-pushable": "^1.4.0", - "libp2p-crypto": "^0.19.0", - "libp2p-tcp": "^0.15.0", - "multiaddr": "^8.1.2", - "multibase": "^3.1.1", - "multihashes": "^3.1.1", - "p-defer": "^3.0.0", - "p-limit": "^3.1.0", - "p-wait-for": "^3.2.0", - "peer-id": "^0.14.2", - "protons": "^2.0.0", - "sinon": "^9.2.4", - "streaming-iterables": "^5.0.4", - "uint8arrays": "^2.0.5" - } - }, - "node_modules/libp2p-kad-dht/node_modules/multiaddr": { - "version": "8.1.2", - "license": "MIT", - "dependencies": { - "cids": "^1.0.0", - "class-is": "^1.1.0", - "dns-over-http-resolver": "^1.0.0", - "err-code": "^2.0.3", - "is-ip": "^3.1.0", - "multibase": "^3.0.0", - "uint8arrays": "^1.1.0", - "varint": "^5.0.0" - } - }, - "node_modules/libp2p-kad-dht/node_modules/multiaddr/node_modules/uint8arrays": { - "version": "1.1.0", - "license": "MIT", - "dependencies": { - "multibase": "^3.0.0", - "web-encoding": "^1.0.2" - } - }, - "node_modules/libp2p-kad-dht/node_modules/multibase": { - "version": "3.1.2", - "license": "MIT", - "dependencies": { - "@multiformats/base-x": "^4.0.1", - "web-encoding": "^1.0.6" - }, - "engines": { - "node": ">=10.0.0", - "npm": ">=6.0.0" - } - }, - "node_modules/libp2p-kad-dht/node_modules/multihashes": { - "version": "3.1.2", - "license": "MIT", - "dependencies": { - "multibase": "^3.1.0", - "uint8arrays": "^2.0.5", - "varint": "^6.0.0" - }, - "engines": { - "node": ">=10.0.0", - "npm": ">=6.0.0" - } - }, - "node_modules/libp2p-kad-dht/node_modules/multihashes/node_modules/varint": { - "version": "6.0.0", - "license": "MIT" - }, - "node_modules/libp2p-kad-dht/node_modules/readable-stream": { - "version": "3.6.0", - "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/libp2p-kad-dht/node_modules/uint8arrays": { - "version": "2.1.10", - "license": "MIT", - "dependencies": { - "multiformats": "^9.4.2" - } - }, - "node_modules/libp2p-kad-dht/node_modules/varint": { - "version": "5.0.2", - "license": "MIT" - }, - "node_modules/libp2p-mplex": { - "version": "0.10.7", - "license": "MIT", - "dependencies": { - "abortable-iterator": "^3.0.2", - "bl": "^5.0.0", - "debug": "^4.3.1", - "err-code": "^3.0.1", - "it-pipe": "^1.1.0", - "it-pushable": "^1.4.1", - "varint": "^6.0.0" - } - }, - "node_modules/libp2p-mplex/node_modules/bl": { - "version": "5.1.0", - "license": "MIT", - "dependencies": { - "buffer": "^6.0.3", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - } - }, - "node_modules/libp2p-mplex/node_modules/err-code": { - "version": "3.0.1", - "license": "MIT" - }, - "node_modules/libp2p-mplex/node_modules/readable-stream": { - "version": "3.6.0", - "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/libp2p-record": { - "version": "0.9.0", - "license": "MIT", - "dependencies": { - "err-code": "^2.0.0", - "multihashes": "^3.0.1", - "multihashing-async": "^2.0.1", - "protons": "^2.0.0", - "uint8arrays": "^1.1.0" - }, - "engines": { - "node": ">=6.0.0", - "npm": ">=3.0.0" - } - }, - "node_modules/libp2p-record/node_modules/multibase": { - "version": "3.1.2", - "license": "MIT", - "dependencies": { - "@multiformats/base-x": "^4.0.1", - "web-encoding": "^1.0.6" - }, - "engines": { - "node": ">=10.0.0", - "npm": ">=6.0.0" - } - }, - "node_modules/libp2p-record/node_modules/multihashes": { - "version": "3.1.2", - "license": "MIT", - "dependencies": { - "multibase": "^3.1.0", - "uint8arrays": "^2.0.5", - "varint": "^6.0.0" - }, - "engines": { - "node": ">=10.0.0", - "npm": ">=6.0.0" - } - }, - "node_modules/libp2p-record/node_modules/multihashes/node_modules/uint8arrays": { - "version": "2.1.10", - "license": "MIT", - "dependencies": { - "multiformats": "^9.4.2" - } - }, - "node_modules/libp2p-record/node_modules/uint8arrays": { - "version": "1.1.0", - "license": "MIT", - "dependencies": { - "multibase": "^3.0.0", - "web-encoding": "^1.0.2" - } - }, - "node_modules/libp2p-tcp": { - "version": "0.15.4", - "license": "MIT", - "dependencies": { - "abortable-iterator": "^3.0.0", - "class-is": "^1.1.0", - "debug": "^4.3.1", - "err-code": "^3.0.1", - "libp2p-utils": "^0.3.0", - "mafmt": "^9.0.0", - "multiaddr": "^9.0.1", - "stream-to-it": "^0.2.2" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/libp2p-tcp/node_modules/err-code": { - "version": "3.0.1", - "license": "MIT" - }, - "node_modules/libp2p-tcp/node_modules/ip-address": { - "version": "7.1.0", - "license": "MIT", - "dependencies": { - "jsbn": "1.1.0", - "sprintf-js": "1.1.2" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/libp2p-tcp/node_modules/libp2p-utils": { - "version": "0.3.1", - "license": "MIT", - "dependencies": { - "abortable-iterator": "^3.0.0", - "debug": "^4.3.0", - "err-code": "^3.0.1", - "ip-address": "^7.1.0", - "is-loopback-addr": "^1.0.0", - "multiaddr": "^9.0.1", - "private-ip": "^2.1.1" - } - }, - "node_modules/libp2p-tcp/node_modules/mafmt": { - "version": "9.0.0", - "license": "MIT", - "dependencies": { - "multiaddr": "^9.0.1" - } - }, - "node_modules/libp2p-tcp/node_modules/multiaddr": { - "version": "9.0.2", - "license": "MIT", - "dependencies": { - "cids": "^1.0.0", - "dns-over-http-resolver": "^1.0.0", - "err-code": "^3.0.1", - "is-ip": "^3.1.0", - "multibase": "^4.0.2", - "uint8arrays": "^2.1.3", - "varint": "^6.0.0" - } - }, - "node_modules/libp2p-tcp/node_modules/uint8arrays": { - "version": "2.1.10", - "license": "MIT", - "dependencies": { - "multiformats": "^9.4.2" - } - }, - "node_modules/libp2p-utils": { - "version": "0.2.3", - "license": "MIT", - "dependencies": { - "abortable-iterator": "^3.0.0", - "debug": "^4.2.0", - "err-code": "^2.0.3", - "ip-address": "^6.1.0", - "is-loopback-addr": "^1.0.0", - "multiaddr": "^8.0.0", - "private-ip": "^2.1.1" - } - }, - "node_modules/libp2p-utils/node_modules/multiaddr": { - "version": "8.1.2", - "license": "MIT", - "dependencies": { - "cids": "^1.0.0", - "class-is": "^1.1.0", - "dns-over-http-resolver": "^1.0.0", - "err-code": "^2.0.3", - "is-ip": "^3.1.0", - "multibase": "^3.0.0", - "uint8arrays": "^1.1.0", - "varint": "^5.0.0" - } - }, - "node_modules/libp2p-utils/node_modules/multibase": { - "version": "3.1.2", - "license": "MIT", - "dependencies": { - "@multiformats/base-x": "^4.0.1", - "web-encoding": "^1.0.6" - }, - "engines": { - "node": ">=10.0.0", - "npm": ">=6.0.0" - } - }, - "node_modules/libp2p-utils/node_modules/uint8arrays": { - "version": "1.1.0", - "license": "MIT", - "dependencies": { - "multibase": "^3.0.0", - "web-encoding": "^1.0.2" - } - }, - "node_modules/libp2p-utils/node_modules/varint": { - "version": "5.0.2", - "license": "MIT" - }, - "node_modules/libp2p-websockets": { - "version": "0.15.9", - "license": "MIT", - "dependencies": { - "abortable-iterator": "^3.0.0", - "class-is": "^1.1.0", - "debug": "^4.3.1", - "err-code": "^3.0.1", - "ipfs-utils": "^8.1.2", - "it-ws": "^4.0.0", - "libp2p-utils": "^0.3.0", - "mafmt": "^9.0.0", - "multiaddr": "^9.0.1", - "multiaddr-to-uri": "^7.0.0", - "p-defer": "^3.0.0", - "p-timeout": "^4.1.0" - } - }, - "node_modules/libp2p-websockets/node_modules/err-code": { - "version": "3.0.1", - "license": "MIT" - }, - "node_modules/libp2p-websockets/node_modules/ip-address": { - "version": "7.1.0", - "license": "MIT", - "dependencies": { - "jsbn": "1.1.0", - "sprintf-js": "1.1.2" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/libp2p-websockets/node_modules/ipfs-utils": { - "version": "8.1.6", - "license": "MIT", - "dependencies": { - "abort-controller": "^3.0.0", - "any-signal": "^2.1.0", - "buffer": "^6.0.1", - "electron-fetch": "^1.7.2", - "err-code": "^3.0.1", - "is-electron": "^2.2.0", - "iso-url": "^1.1.5", - "it-glob": "~0.0.11", - "it-to-stream": "^1.0.0", - "merge-options": "^3.0.4", - "nanoid": "^3.1.20", - "native-abort-controller": "^1.0.3", - "native-fetch": "^3.0.0", - "node-fetch": "https://registry.npmjs.org/@achingbrain/node-fetch/-/node-fetch-2.6.7.tgz", - "react-native-fetch-api": "^2.0.0", - "stream-to-it": "^0.2.2" - } - }, - "node_modules/libp2p-websockets/node_modules/libp2p-utils": { - "version": "0.3.1", - "license": "MIT", - "dependencies": { - "abortable-iterator": "^3.0.0", - "debug": "^4.3.0", - "err-code": "^3.0.1", - "ip-address": "^7.1.0", - "is-loopback-addr": "^1.0.0", - "multiaddr": "^9.0.1", - "private-ip": "^2.1.1" - } - }, - "node_modules/libp2p-websockets/node_modules/mafmt": { - "version": "9.0.0", - "license": "MIT", - "dependencies": { - "multiaddr": "^9.0.1" - } - }, - "node_modules/libp2p-websockets/node_modules/multiaddr": { - "version": "9.0.2", - "license": "MIT", - "dependencies": { - "cids": "^1.0.0", - "dns-over-http-resolver": "^1.0.0", - "err-code": "^3.0.1", - "is-ip": "^3.1.0", - "multibase": "^4.0.2", - "uint8arrays": "^2.1.3", - "varint": "^6.0.0" - } - }, - "node_modules/libp2p-websockets/node_modules/node-fetch": { - "name": "@achingbrain/node-fetch", - "version": "2.6.7", - "license": "MIT", - "engines": { - "node": "4.x || >=6.0.0" - } - }, - "node_modules/libp2p-websockets/node_modules/uint8arrays": { - "version": "2.1.10", - "license": "MIT", - "dependencies": { - "multiformats": "^9.4.2" - } - }, - "node_modules/libp2p/node_modules/bl": { - "version": "4.1.0", - "license": "MIT", - "dependencies": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - } - }, - "node_modules/libp2p/node_modules/buffer": { - "version": "5.7.1", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, - "node_modules/libp2p/node_modules/delay": { - "version": "4.4.1", - "license": "MIT", - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/libp2p/node_modules/es6-promisify": { - "version": "6.1.1", - "license": "MIT" - }, - "node_modules/libp2p/node_modules/events": { - "version": "3.3.0", - "license": "MIT", - "engines": { - "node": ">=0.8.x" - } - }, - "node_modules/libp2p/node_modules/it-handshake": { - "version": "1.0.2", - "license": "MIT", - "dependencies": { - "it-pushable": "^1.4.0", - "it-reader": "^2.0.0", - "p-defer": "^3.0.0" - } - }, - "node_modules/libp2p/node_modules/it-length-prefixed": { - "version": "3.1.0", - "license": "MIT", - "dependencies": { - "@types/bl": "^2.1.0", - "bl": "^4.0.2", - "buffer": "^5.5.0", - "varint": "^5.0.0" - } - }, - "node_modules/libp2p/node_modules/it-length-prefixed/node_modules/varint": { - "version": "5.0.2", - "license": "MIT" - }, - "node_modules/libp2p/node_modules/it-reader": { - "version": "2.1.0", - "license": "MIT", - "dependencies": { - "bl": "^4.0.0" - } - }, - "node_modules/libp2p/node_modules/libp2p-interfaces": { - "version": "0.8.4", - "license": "MIT", - "dependencies": { - "@types/bl": "^2.1.0", - "abort-controller": "^3.0.0", - "abortable-iterator": "^3.0.0", - "chai": "^4.2.0", - "chai-checkmark": "^1.0.1", - "debug": "^4.3.1", - "delay": "^4.4.0", - "detect-node": "^2.0.4", - "dirty-chai": "^2.0.1", - "err-code": "^2.0.3", - "it-goodbye": "^2.0.2", - "it-length-prefixed": "^3.1.0", - "it-pair": "^1.0.0", - "it-pipe": "^1.1.0", - "it-pushable": "^1.4.0", - "libp2p-crypto": "^0.19.0", - "libp2p-tcp": "^0.15.0", - "multiaddr": "^8.1.2", - "multibase": "^3.1.1", - "multihashes": "^3.1.1", - "p-defer": "^3.0.0", - "p-limit": "^3.1.0", - "p-wait-for": "^3.2.0", - "peer-id": "^0.14.2", - "protons": "^2.0.0", - "sinon": "^9.2.4", - "streaming-iterables": "^5.0.4", - "uint8arrays": "^2.0.5" - } - }, - "node_modules/libp2p/node_modules/multiaddr": { - "version": "8.1.2", - "license": "MIT", - "dependencies": { - "cids": "^1.0.0", - "class-is": "^1.1.0", - "dns-over-http-resolver": "^1.0.0", - "err-code": "^2.0.3", - "is-ip": "^3.1.0", - "multibase": "^3.0.0", - "uint8arrays": "^1.1.0", - "varint": "^5.0.0" - } - }, - "node_modules/libp2p/node_modules/multiaddr/node_modules/uint8arrays": { - "version": "1.1.0", - "license": "MIT", - "dependencies": { - "multibase": "^3.0.0", - "web-encoding": "^1.0.2" - } - }, - "node_modules/libp2p/node_modules/multiaddr/node_modules/varint": { - "version": "5.0.2", - "license": "MIT" - }, - "node_modules/libp2p/node_modules/multibase": { - "version": "3.1.2", - "license": "MIT", - "dependencies": { - "@multiformats/base-x": "^4.0.1", - "web-encoding": "^1.0.6" - }, - "engines": { - "node": ">=10.0.0", - "npm": ">=6.0.0" - } - }, - "node_modules/libp2p/node_modules/multihashes": { - "version": "3.1.2", - "license": "MIT", - "dependencies": { - "multibase": "^3.1.0", - "uint8arrays": "^2.0.5", - "varint": "^6.0.0" - }, - "engines": { - "node": ">=10.0.0", - "npm": ">=6.0.0" - } - }, - "node_modules/libp2p/node_modules/readable-stream": { - "version": "3.6.0", - "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/libp2p/node_modules/uint8arrays": { - "version": "2.1.10", - "license": "MIT", - "dependencies": { - "multiformats": "^9.4.2" - } - }, - "node_modules/lilconfig": { - "version": "2.0.5", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - } - }, - "node_modules/lint-staged": { - "version": "13.0.3", - "dev": true, - "license": "MIT", - "dependencies": { - "cli-truncate": "^3.1.0", - "colorette": "^2.0.17", - "commander": "^9.3.0", - "debug": "^4.3.4", - "execa": "^6.1.0", - "lilconfig": "2.0.5", - "listr2": "^4.0.5", - "micromatch": "^4.0.5", - "normalize-path": "^3.0.0", - "object-inspect": "^1.12.2", - "pidtree": "^0.6.0", - "string-argv": "^0.3.1", - "yaml": "^2.1.1" - }, - "bin": { - "lint-staged": "bin/lint-staged.js" - }, - "engines": { - "node": "^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/lint-staged" - } - }, - "node_modules/lint-staged/node_modules/commander": { - "version": "9.4.1", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.20.0 || >=14" - } - }, - "node_modules/lint-staged/node_modules/execa": { - "version": "6.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.1", - "human-signals": "^3.0.1", - "is-stream": "^3.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^5.1.0", - "onetime": "^6.0.0", - "signal-exit": "^3.0.7", - "strip-final-newline": "^3.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/lint-staged/node_modules/human-signals": { - "version": "3.0.1", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=12.20.0" - } - }, - "node_modules/lint-staged/node_modules/is-stream": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lint-staged/node_modules/mimic-fn": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lint-staged/node_modules/npm-run-path": { - "version": "5.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "path-key": "^4.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lint-staged/node_modules/onetime": { - "version": "6.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "mimic-fn": "^4.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lint-staged/node_modules/path-key": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lint-staged/node_modules/strip-final-newline": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/listr2": { - "version": "4.0.5", - "dev": true, - "license": "MIT", - "dependencies": { - "cli-truncate": "^2.1.0", - "colorette": "^2.0.16", - "log-update": "^4.0.0", - "p-map": "^4.0.0", - "rfdc": "^1.3.0", - "rxjs": "^7.5.5", - "through": "^2.3.8", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - }, - "peerDependencies": { - "enquirer": ">= 2.3.0 < 3" - }, - "peerDependenciesMeta": { - "enquirer": { - "optional": true - } - } - }, - "node_modules/listr2/node_modules/cli-truncate": { - "version": "2.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "slice-ansi": "^3.0.0", - "string-width": "^4.2.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/listr2/node_modules/emoji-regex": { - "version": "8.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/listr2/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/listr2/node_modules/slice-ansi": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/listr2/node_modules/string-width": { - "version": "4.2.3", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/lmdb": { - "version": "2.6.8", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "dependencies": { - "msgpackr": "1.7.2", - "node-addon-api": "^4.3.0", - "node-gyp-build-optional-packages": "5.0.3", - "ordered-binary": "^1.4.0", - "weak-lru-cache": "^1.2.2" - }, - "bin": { - "download-lmdb-prebuilds": "bin/download-prebuilds.js" - }, - "optionalDependencies": { - "@lmdb/lmdb-darwin-arm64": "2.6.8", - "@lmdb/lmdb-darwin-x64": "2.6.8", - "@lmdb/lmdb-linux-arm": "2.6.8", - "@lmdb/lmdb-linux-arm64": "2.6.8", - "@lmdb/lmdb-linux-x64": "2.6.8", - "@lmdb/lmdb-win32-x64": "2.6.8" - } - }, - "node_modules/load-json-file": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.1.2", - "parse-json": "^4.0.0", - "pify": "^3.0.0", - "strip-bom": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/load-json-file/node_modules/strip-bom": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/loader-runner": { - "version": "4.3.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.11.5" - } - }, - "node_modules/loader-utils": { - "version": "2.0.3", - "dev": true, - "license": "MIT", - "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" - }, - "engines": { - "node": ">=8.9.0" - } - }, - "node_modules/locate-path": { - "version": "6.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lodash": { - "version": "4.17.21", - "license": "MIT" - }, - "node_modules/lodash.camelcase": { - "version": "4.3.0", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.cond": { - "version": "4.5.2", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.debounce": { - "version": "4.0.8", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.find": { - "version": "4.6.0", - "license": "MIT" - }, - "node_modules/lodash.flattendeep": { - "version": "4.4.0", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.get": { - "version": "4.4.2", - "license": "MIT" - }, - "node_modules/lodash.kebabcase": { - "version": "4.1.1", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.max": { - "version": "4.0.1", - "license": "MIT" - }, - "node_modules/lodash.memoize": { - "version": "3.0.4", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "license": "MIT" - }, - "node_modules/lodash.padstart": { - "version": "4.6.1", - "license": "MIT" - }, - "node_modules/lodash.repeat": { - "version": "4.1.0", - "license": "MIT" - }, - "node_modules/lodash.snakecase": { - "version": "4.1.1", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.upperfirst": { - "version": "4.3.1", - "dev": true, - "license": "MIT" - }, - "node_modules/log-update": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-escapes": "^4.3.0", - "cli-cursor": "^3.1.0", - "slice-ansi": "^4.0.0", - "wrap-ansi": "^6.2.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-update/node_modules/emoji-regex": { - "version": "8.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/log-update/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/log-update/node_modules/slice-ansi": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" - } - }, - "node_modules/log-update/node_modules/string-width": { - "version": "4.2.3", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/log-update/node_modules/wrap-ansi": { - "version": "6.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/log4js": { - "version": "6.7.0", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "date-format": "^4.0.14", - "debug": "^4.3.4", - "flatted": "^3.2.7", - "rfdc": "^1.3.0", - "streamroller": "^3.1.3" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/logform": { - "version": "2.4.2", - "license": "MIT", - "dependencies": { - "@colors/colors": "1.5.0", - "fecha": "^4.2.0", - "ms": "^2.1.1", - "safe-stable-stringify": "^2.3.1", - "triple-beam": "^1.3.0" - } - }, - "node_modules/logform/node_modules/ms": { - "version": "2.1.3", - "license": "MIT" - }, - "node_modules/lolex": { - "version": "1.6.0", - "dev": true, - "license": "BSD-3-Clause" - }, - "node_modules/long": { - "version": "4.0.0", - "license": "Apache-2.0" - }, - "node_modules/loupe": { - "version": "2.3.4", - "license": "MIT", - "dependencies": { - "get-func-name": "^2.0.0" - } - }, - "node_modules/lower-case": { - "version": "1.1.4", - "dev": true, - "license": "MIT" - }, - "node_modules/lru-cache": { - "version": "7.18.3", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/ltgt": { - "version": "2.2.1", - "dev": true, - "license": "MIT" - }, - "node_modules/lunr": { - "version": "2.3.9", - "dev": true, - "license": "MIT" - }, - "node_modules/mafmt": { - "version": "8.0.4", - "license": "MIT", - "dependencies": { - "multiaddr": "^8.0.0" - } - }, - "node_modules/mafmt/node_modules/multiaddr": { - "version": "8.1.2", - "license": "MIT", - "dependencies": { - "cids": "^1.0.0", - "class-is": "^1.1.0", - "dns-over-http-resolver": "^1.0.0", - "err-code": "^2.0.3", - "is-ip": "^3.1.0", - "multibase": "^3.0.0", - "uint8arrays": "^1.1.0", - "varint": "^5.0.0" - } - }, - "node_modules/mafmt/node_modules/multibase": { - "version": "3.1.2", - "license": "MIT", - "dependencies": { - "@multiformats/base-x": "^4.0.1", - "web-encoding": "^1.0.6" - }, - "engines": { - "node": ">=10.0.0", - "npm": ">=6.0.0" - } - }, - "node_modules/mafmt/node_modules/uint8arrays": { - "version": "1.1.0", - "license": "MIT", - "dependencies": { - "multibase": "^3.0.0", - "web-encoding": "^1.0.2" - } - }, - "node_modules/mafmt/node_modules/varint": { - "version": "5.0.2", - "license": "MIT" - }, - "node_modules/magic-string": { - "version": "0.25.9", - "dev": true, - "license": "MIT", - "dependencies": { - "sourcemap-codec": "^1.4.8" - } - }, - "node_modules/make-dir": { - "version": "1.3.0", - "dev": true, - "license": "MIT", - "dependencies": { - "pify": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/make-error": { - "version": "1.3.6", - "dev": true, - "license": "ISC" - }, - "node_modules/marked": { - "version": "4.1.1", - "dev": true, - "license": "MIT", - "bin": { - "marked": "bin/marked.js" - }, - "engines": { - "node": ">= 12" - } - }, - "node_modules/mcl-wasm": { - "version": "0.7.9", - "license": "BSD-3-Clause", - "engines": { - "node": ">=8.9.0" - } - }, - "node_modules/md5.js": { - "version": "1.3.5", - "dev": true, - "license": "MIT", - "dependencies": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "node_modules/media-typer": { - "version": "0.3.0", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/memdown": { - "version": "6.1.1", - "dev": true, - "license": "MIT", - "dependencies": { - "abstract-leveldown": "^7.2.0", - "buffer": "^6.0.3", - "functional-red-black-tree": "^1.0.1", - "inherits": "^2.0.1", - "ltgt": "^2.2.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/memory-level": { - "version": "1.0.0", - "license": "MIT", - "dependencies": { - "abstract-level": "^1.0.0", - "functional-red-black-tree": "^1.0.1", - "module-error": "^1.0.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/memorystream": { - "version": "0.3.1", - "dev": true, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/merge-options": { - "version": "3.0.4", - "license": "MIT", - "dependencies": { - "is-plain-obj": "^2.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/merge-source-map": { - "version": "1.0.4", - "dev": true, - "license": "MIT", - "dependencies": { - "source-map": "^0.5.6" - } - }, - "node_modules/merge-stream": { - "version": "2.0.0", - "license": "MIT" - }, - "node_modules/merge2": { - "version": "1.4.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/methods": { - "version": "1.1.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/micro-bmark": { - "version": "0.2.0", - "dev": true, - "license": "MIT" - }, - "node_modules/micromatch": { - "version": "4.0.5", - "dev": true, - "license": "MIT", - "dependencies": { - "braces": "^3.0.2", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/miller-rabin": { - "version": "4.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "bn.js": "^4.0.0", - "brorand": "^1.0.1" - }, - "bin": { - "miller-rabin": "bin/miller-rabin" - } - }, - "node_modules/miller-rabin/node_modules/bn.js": { - "version": "4.12.0", - "dev": true, - "license": "MIT" - }, - "node_modules/mime": { - "version": "2.6.0", - "dev": true, - "license": "MIT", - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/mime-db": { - "version": "1.52.0", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "license": "MIT", - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mimic-fn": { - "version": "2.1.0", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/minimalistic-assert": { - "version": "1.0.1", - "license": "ISC" - }, - "node_modules/minimalistic-crypto-utils": { - "version": "1.0.1", - "license": "MIT" - }, - "node_modules/minimatch": { - "version": "3.1.2", - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/minimist": { - "version": "1.2.7", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/mkdirp": { - "version": "0.5.6", - "dev": true, - "license": "MIT", - "dependencies": { - "minimist": "^1.2.6" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, - "node_modules/mkdirp-classic": { - "version": "0.5.3", - "dev": true, - "license": "MIT" - }, - "node_modules/module-deps": { - "version": "6.2.3", - "dev": true, - "license": "MIT", - "dependencies": { - "browser-resolve": "^2.0.0", - "cached-path-relative": "^1.0.2", - "concat-stream": "~1.6.0", - "defined": "^1.0.0", - "detective": "^5.2.0", - "duplexer2": "^0.1.2", - "inherits": "^2.0.1", - "JSONStream": "^1.0.3", - "parents": "^1.0.0", - "readable-stream": "^2.0.2", - "resolve": "^1.4.0", - "stream-combiner2": "^1.1.1", - "subarg": "^1.0.0", - "through2": "^2.0.0", - "xtend": "^4.0.0" - }, - "bin": { - "module-deps": "bin/cmd.js" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/module-error": { - "version": "1.0.2", - "license": "MIT", - "engines": { - "node": ">=10" - } - }, - "node_modules/moment": { - "version": "2.29.4", - "license": "MIT", - "engines": { - "node": "*" - } - }, - "node_modules/morphdom": { - "version": "2.6.1", - "dev": true, - "license": "MIT" - }, - "node_modules/moving-average": { - "version": "1.0.1", - "license": "MIT" - }, - "node_modules/ms": { - "version": "0.7.3", - "license": "MIT" - }, - "node_modules/msgpackr": { - "version": "1.7.2", - "dev": true, - "license": "MIT", - "optionalDependencies": { - "msgpackr-extract": "^2.1.2" - } - }, - "node_modules/msgpackr-extract": { - "version": "2.1.2", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "dependencies": { - "node-gyp-build-optional-packages": "5.0.3" - }, - "bin": { - "download-msgpackr-prebuilds": "bin/download-prebuilds.js" - }, - "optionalDependencies": { - "@msgpackr-extract/msgpackr-extract-darwin-arm64": "2.1.2", - "@msgpackr-extract/msgpackr-extract-darwin-x64": "2.1.2", - "@msgpackr-extract/msgpackr-extract-linux-arm": "2.1.2", - "@msgpackr-extract/msgpackr-extract-linux-arm64": "2.1.2", - "@msgpackr-extract/msgpackr-extract-linux-x64": "2.1.2", - "@msgpackr-extract/msgpackr-extract-win32-x64": "2.1.2" - } - }, - "node_modules/multiaddr": { - "version": "10.0.1", - "license": "MIT", - "dependencies": { - "dns-over-http-resolver": "^1.2.3", - "err-code": "^3.0.1", - "is-ip": "^3.1.0", - "multiformats": "^9.4.5", - "uint8arrays": "^3.0.0", - "varint": "^6.0.0" - } - }, - "node_modules/multiaddr-to-uri": { - "version": "7.0.0", - "license": "MIT", - "dependencies": { - "multiaddr": "^9.0.1" - } - }, - "node_modules/multiaddr-to-uri/node_modules/err-code": { - "version": "3.0.1", - "license": "MIT" - }, - "node_modules/multiaddr-to-uri/node_modules/multiaddr": { - "version": "9.0.2", - "license": "MIT", - "dependencies": { - "cids": "^1.0.0", - "dns-over-http-resolver": "^1.0.0", - "err-code": "^3.0.1", - "is-ip": "^3.1.0", - "multibase": "^4.0.2", - "uint8arrays": "^2.1.3", - "varint": "^6.0.0" - } - }, - "node_modules/multiaddr-to-uri/node_modules/uint8arrays": { - "version": "2.1.10", - "license": "MIT", - "dependencies": { - "multiformats": "^9.4.2" - } - }, - "node_modules/multiaddr/node_modules/err-code": { - "version": "3.0.1", - "license": "MIT" - }, - "node_modules/multibase": { - "version": "4.0.6", - "license": "MIT", - "dependencies": { - "@multiformats/base-x": "^4.0.1" - }, - "engines": { - "node": ">=12.0.0", - "npm": ">=6.0.0" - } - }, - "node_modules/multicodec": { - "version": "2.1.3", - "license": "MIT", - "dependencies": { - "uint8arrays": "1.1.0", - "varint": "^6.0.0" - } - }, - "node_modules/multicodec/node_modules/multibase": { - "version": "3.1.2", - "license": "MIT", - "dependencies": { - "@multiformats/base-x": "^4.0.1", - "web-encoding": "^1.0.6" - }, - "engines": { - "node": ">=10.0.0", - "npm": ">=6.0.0" - } - }, - "node_modules/multicodec/node_modules/uint8arrays": { - "version": "1.1.0", - "license": "MIT", - "dependencies": { - "multibase": "^3.0.0", - "web-encoding": "^1.0.2" - } - }, - "node_modules/multiformats": { - "version": "9.9.0", - "license": "(Apache-2.0 AND MIT)" - }, - "node_modules/multihashes": { - "version": "4.0.3", - "license": "MIT", - "dependencies": { - "multibase": "^4.0.1", - "uint8arrays": "^3.0.0", - "varint": "^5.0.2" - }, - "engines": { - "node": ">=12.0.0", - "npm": ">=6.0.0" - } - }, - "node_modules/multihashes/node_modules/varint": { - "version": "5.0.2", - "license": "MIT" - }, - "node_modules/multihashing-async": { - "version": "2.1.4", - "license": "MIT", - "dependencies": { - "blakejs": "^1.1.0", - "err-code": "^3.0.0", - "js-sha3": "^0.8.0", - "multihashes": "^4.0.1", - "murmurhash3js-revisited": "^3.0.0", - "uint8arrays": "^3.0.0" - }, - "engines": { - "node": ">=12.0.0", - "npm": ">=6.0.0" - } - }, - "node_modules/multihashing-async/node_modules/err-code": { - "version": "3.0.1", - "license": "MIT" - }, - "node_modules/multistream-select": { - "version": "1.0.0", - "license": "MIT", - "dependencies": { - "bl": "^4.0.0", - "debug": "^4.1.1", - "err-code": "^2.0.0", - "it-handshake": "^1.0.2", - "it-length-prefixed": "^3.0.0", - "it-pipe": "^1.0.1", - "it-reader": "^2.0.0", - "p-defer": "^3.0.0", - "uint8arrays": "^1.1.0" - } - }, - "node_modules/multistream-select/node_modules/bl": { - "version": "4.1.0", - "license": "MIT", - "dependencies": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - } - }, - "node_modules/multistream-select/node_modules/buffer": { - "version": "5.7.1", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, - "node_modules/multistream-select/node_modules/it-handshake": { - "version": "1.0.2", - "license": "MIT", - "dependencies": { - "it-pushable": "^1.4.0", - "it-reader": "^2.0.0", - "p-defer": "^3.0.0" - } - }, - "node_modules/multistream-select/node_modules/it-length-prefixed": { - "version": "3.1.0", - "license": "MIT", - "dependencies": { - "@types/bl": "^2.1.0", - "bl": "^4.0.2", - "buffer": "^5.5.0", - "varint": "^5.0.0" - } - }, - "node_modules/multistream-select/node_modules/it-reader": { - "version": "2.1.0", - "license": "MIT", - "dependencies": { - "bl": "^4.0.0" - } - }, - "node_modules/multistream-select/node_modules/multibase": { - "version": "3.1.2", - "license": "MIT", - "dependencies": { - "@multiformats/base-x": "^4.0.1", - "web-encoding": "^1.0.6" - }, - "engines": { - "node": ">=10.0.0", - "npm": ">=6.0.0" - } - }, - "node_modules/multistream-select/node_modules/readable-stream": { - "version": "3.6.0", - "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/multistream-select/node_modules/uint8arrays": { - "version": "1.1.0", - "license": "MIT", - "dependencies": { - "multibase": "^3.0.0", - "web-encoding": "^1.0.2" - } - }, - "node_modules/multistream-select/node_modules/varint": { - "version": "5.0.2", - "license": "MIT" - }, - "node_modules/murmurhash3js-revisited": { - "version": "3.0.0", - "license": "MIT", - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/mutable-proxy": { - "version": "1.0.0", - "license": "MIT", - "engines": { - "node": ">=6.X.X", - "npm": ">=3.X.X" - } - }, - "node_modules/mute-stream": { - "version": "0.0.5", - "dev": true, - "license": "ISC" - }, - "node_modules/mutexify": { - "version": "1.4.0", - "dev": true, - "license": "MIT", - "dependencies": { - "queue-tick": "^1.0.0" - } - }, - "node_modules/nan": { - "version": "2.17.0", - "license": "MIT" - }, - "node_modules/nanoassert": { - "version": "1.1.0", - "dev": true, - "license": "ISC" - }, - "node_modules/nanobench": { - "version": "2.1.1", - "dev": true, - "license": "MIT", - "dependencies": { - "browser-process-hrtime": "^0.1.2", - "chalk": "^1.1.3", - "mutexify": "^1.1.0", - "pretty-hrtime": "^1.0.2" - }, - "bin": { - "nanobench": "run.js", - "nanobench-compare": "compare.js" - } - }, - "node_modules/nanobench/node_modules/ansi-regex": { - "version": "2.1.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/nanobench/node_modules/ansi-styles": { - "version": "2.2.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/nanobench/node_modules/chalk": { - "version": "1.1.3", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/nanobench/node_modules/strip-ansi": { - "version": "3.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/nanobench/node_modules/supports-color": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/nanohtml": { - "version": "1.10.0", - "dev": true, - "license": "MIT", - "dependencies": { - "acorn-node": "^1.8.2", - "camel-case": "^3.0.0", - "convert-source-map": "^1.5.1", - "estree-is-member-expression": "^1.0.0", - "hyperx": "^2.5.0", - "is-boolean-attribute": "0.0.1", - "nanoassert": "^1.1.0", - "nanobench": "^2.1.0", - "normalize-html-whitespace": "^0.2.0", - "through2": "^2.0.3", - "transform-ast": "^2.4.0" - } - }, - "node_modules/nanohtml/node_modules/convert-source-map": { - "version": "1.9.0", - "dev": true, - "license": "MIT" - }, - "node_modules/nanoid": { - "version": "3.3.4", - "license": "MIT", - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/napi-macros": { - "version": "2.0.0", - "license": "MIT" - }, - "node_modules/native-abort-controller": { - "version": "1.0.4", - "license": "MIT", - "peerDependencies": { - "abort-controller": "*" - } - }, - "node_modules/native-fetch": { - "version": "3.0.0", - "license": "MIT", - "peerDependencies": { - "node-fetch": "*" - } - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "dev": true, - "license": "MIT" - }, - "node_modules/negotiator": { - "version": "0.6.3", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/neo-async": { - "version": "2.6.2", - "dev": true, - "license": "MIT" - }, - "node_modules/netmask": { - "version": "2.0.2", - "license": "MIT", - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/next-tick": { - "version": "1.1.0", - "dev": true, - "license": "ISC" - }, - "node_modules/nise": { - "version": "4.1.0", - "license": "BSD-3-Clause", - "dependencies": { - "@sinonjs/commons": "^1.7.0", - "@sinonjs/fake-timers": "^6.0.0", - "@sinonjs/text-encoding": "^0.7.1", - "just-extend": "^4.0.2", - "path-to-regexp": "^1.7.0" - } - }, - "node_modules/no-case": { - "version": "2.3.2", - "dev": true, - "license": "MIT", - "dependencies": { - "lower-case": "^1.1.1" - } - }, - "node_modules/noble-ed25519": { - "version": "1.2.6", - "license": "MIT" - }, - "node_modules/noble-secp256k1": { - "version": "1.2.14", - "license": "MIT" - }, - "node_modules/node-addon-api": { - "version": "4.3.0", - "dev": true, - "license": "MIT" - }, - "node_modules/node-dir": { - "version": "0.1.17", - "dev": true, - "license": "MIT", - "dependencies": { - "minimatch": "^3.0.2" - }, - "engines": { - "node": ">= 0.10.5" - } - }, - "node_modules/node-fetch": { - "version": "2.6.7", - "license": "MIT", - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, - "node_modules/node-forge": { - "version": "0.10.0", - "license": "(BSD-3-Clause OR GPL-2.0)", - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/node-gyp-build": { - "version": "4.5.0", - "license": "MIT", - "bin": { - "node-gyp-build": "bin.js", - "node-gyp-build-optional": "optional.js", - "node-gyp-build-test": "build-test.js" - } - }, - "node_modules/node-gyp-build-optional-packages": { - "version": "5.0.3", - "dev": true, - "license": "MIT", - "bin": { - "node-gyp-build-optional-packages": "bin.js", - "node-gyp-build-optional-packages-optional": "optional.js", - "node-gyp-build-optional-packages-test": "build-test.js" - } - }, - "node_modules/node-preload": { - "version": "0.2.1", - "dev": true, - "license": "MIT", - "dependencies": { - "process-on-spawn": "^1.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/node-releases": { - "version": "2.0.6", - "dev": true, - "license": "MIT" - }, - "node_modules/normalize-html-whitespace": { - "version": "0.2.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/npm-run-path": { - "version": "4.0.1", - "license": "MIT", - "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/number-is-nan": { - "version": "1.0.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/nyc": { - "version": "15.1.0", - "dev": true, - "license": "ISC", - "dependencies": { - "@istanbuljs/load-nyc-config": "^1.0.0", - "@istanbuljs/schema": "^0.1.2", - "caching-transform": "^4.0.0", - "convert-source-map": "^1.7.0", - "decamelize": "^1.2.0", - "find-cache-dir": "^3.2.0", - "find-up": "^4.1.0", - "foreground-child": "^2.0.0", - "get-package-type": "^0.1.0", - "glob": "^7.1.6", - "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-hook": "^3.0.0", - "istanbul-lib-instrument": "^4.0.0", - "istanbul-lib-processinfo": "^2.0.2", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^4.0.0", - "istanbul-reports": "^3.0.2", - "make-dir": "^3.0.0", - "node-preload": "^0.2.1", - "p-map": "^3.0.0", - "process-on-spawn": "^1.0.0", - "resolve-from": "^5.0.0", - "rimraf": "^3.0.0", - "signal-exit": "^3.0.2", - "spawn-wrap": "^2.0.0", - "test-exclude": "^6.0.0", - "yargs": "^15.0.2" - }, - "bin": { - "nyc": "bin/nyc.js" - }, - "engines": { - "node": ">=8.9" - } - }, - "node_modules/nyc/node_modules/cliui": { - "version": "6.0.0", - "dev": true, - "license": "ISC", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^6.2.0" - } - }, - "node_modules/nyc/node_modules/convert-source-map": { - "version": "1.9.0", - "dev": true, - "license": "MIT" - }, - "node_modules/nyc/node_modules/emoji-regex": { - "version": "8.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/nyc/node_modules/find-up": { - "version": "4.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/nyc/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/nyc/node_modules/locate-path": { - "version": "5.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/nyc/node_modules/make-dir": { - "version": "3.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "semver": "^6.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/nyc/node_modules/p-limit": { - "version": "2.3.0", - "dev": true, - "license": "MIT", - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/nyc/node_modules/p-locate": { - "version": "4.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/nyc/node_modules/p-map": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "aggregate-error": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/nyc/node_modules/resolve-from": { - "version": "5.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/nyc/node_modules/semver": { - "version": "6.3.0", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/nyc/node_modules/string-width": { - "version": "4.2.3", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/nyc/node_modules/wrap-ansi": { - "version": "6.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/nyc/node_modules/y18n": { - "version": "4.0.3", - "dev": true, - "license": "ISC" - }, - "node_modules/nyc/node_modules/yargs": { - "version": "15.4.1", - "dev": true, - "license": "MIT", - "dependencies": { - "cliui": "^6.0.0", - "decamelize": "^1.2.0", - "find-up": "^4.1.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^4.2.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^18.1.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/nyc/node_modules/yargs-parser": { - "version": "18.1.3", - "dev": true, - "license": "ISC", - "dependencies": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/oauth-sign": { - "version": "0.9.0", - "license": "Apache-2.0", - "engines": { - "node": "*" - } - }, - "node_modules/object-assign": { - "version": "4.1.1", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-hash": { - "version": "2.2.0", - "license": "MIT", - "engines": { - "node": ">= 6" - } - }, - "node_modules/object-inspect": { - "version": "1.12.2", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-is": { - "version": "1.1.5", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-keys": { - "version": "1.1.1", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.assign": { - "version": "4.1.4", - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "has-symbols": "^1.0.3", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.values": { - "version": "1.1.5", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/on-finished": { - "version": "2.4.1", - "license": "MIT", - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/on-net-listen": { - "version": "1.1.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=9.4.0 || ^8.9.4" - } - }, - "node_modules/once": { - "version": "1.4.0", - "dev": true, - "license": "ISC", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/one-time": { - "version": "1.0.0", - "license": "MIT", - "dependencies": { - "fn.name": "1.x.x" - } - }, - "node_modules/onetime": { - "version": "5.1.2", - "license": "MIT", - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/opn": { - "version": "5.5.0", - "dev": true, - "license": "MIT", - "dependencies": { - "is-wsl": "^1.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/opn/node_modules/is-wsl": { - "version": "1.1.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/optionator": { - "version": "0.9.1", - "dev": true, - "license": "MIT", - "dependencies": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/ordered-binary": { - "version": "1.4.0", - "dev": true, - "license": "MIT" - }, - "node_modules/os-browserify": { - "version": "0.3.0", - "dev": true, - "license": "MIT" - }, - "node_modules/os-homedir": { - "version": "1.0.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/os-tmpdir": { - "version": "1.0.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/p-any": { - "version": "3.0.0", - "license": "MIT", - "dependencies": { - "p-cancelable": "^2.0.0", - "p-some": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-cancelable": { - "version": "2.1.1", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/p-defer": { - "version": "3.0.0", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/p-fifo": { - "version": "1.0.0", - "license": "MIT", - "dependencies": { - "fast-fifo": "^1.0.0", - "p-defer": "^3.0.0" - } - }, - "node_modules/p-filter": { - "version": "2.1.0", - "license": "MIT", - "dependencies": { - "p-map": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/p-filter/node_modules/p-map": { - "version": "2.1.0", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/p-finally": { - "version": "1.0.0", - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/p-limit": { - "version": "3.1.0", - "license": "MIT", - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "5.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-map": { - "version": "4.0.0", - "license": "MIT", - "dependencies": { - "aggregate-error": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-queue": { - "version": "6.6.2", - "license": "MIT", - "dependencies": { - "eventemitter3": "^4.0.4", - "p-timeout": "^3.2.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-queue/node_modules/p-timeout": { - "version": "3.2.0", - "license": "MIT", - "dependencies": { - "p-finally": "^1.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/p-reflect": { - "version": "2.1.0", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/p-retry": { - "version": "4.6.2", - "license": "MIT", - "dependencies": { - "@types/retry": "0.12.0", - "retry": "^0.13.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/p-settle": { - "version": "4.1.1", - "license": "MIT", - "dependencies": { - "p-limit": "^2.2.2", - "p-reflect": "^2.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-settle/node_modules/p-limit": { - "version": "2.3.0", - "license": "MIT", - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-some": { - "version": "5.0.0", - "license": "MIT", - "dependencies": { - "aggregate-error": "^3.0.0", - "p-cancelable": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-timeout": { - "version": "4.1.0", - "license": "MIT", - "engines": { - "node": ">=10" - } - }, - "node_modules/p-times": { - "version": "3.0.0", - "license": "MIT", - "dependencies": { - "p-map": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-try": { - "version": "2.2.0", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/p-wait-for": { - "version": "3.2.0", - "license": "MIT", - "dependencies": { - "p-timeout": "^3.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-wait-for/node_modules/p-timeout": { - "version": "3.2.0", - "license": "MIT", - "dependencies": { - "p-finally": "^1.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/package-hash": { - "version": "4.0.0", - "dev": true, - "license": "ISC", - "dependencies": { - "graceful-fs": "^4.1.15", - "hasha": "^5.0.0", - "lodash.flattendeep": "^4.4.0", - "release-zalgo": "^1.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pad": { - "version": "3.2.0", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "wcwidth": "^1.0.1" - }, - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/pako": { - "version": "1.0.11", - "dev": true, - "license": "(MIT AND Zlib)" - }, - "node_modules/parent-module": { - "version": "1.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/parents": { - "version": "1.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "path-platform": "~0.11.15" - } - }, - "node_modules/parse-asn1": { - "version": "5.1.6", - "dev": true, - "license": "ISC", - "dependencies": { - "asn1.js": "^5.2.0", - "browserify-aes": "^1.0.0", - "evp_bytestokey": "^1.0.0", - "pbkdf2": "^3.0.3", - "safe-buffer": "^5.1.1" - } - }, - "node_modules/parse-json": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/parseurl": { - "version": "1.3.3", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/path-browserify": { - "version": "0.0.1", - "dev": true, - "license": "MIT" - }, - "node_modules/path-exists": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-is-inside": { - "version": "1.0.2", - "dev": true, - "license": "(WTFPL OR MIT)" - }, - "node_modules/path-key": { - "version": "3.1.1", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "dev": true, - "license": "MIT" - }, - "node_modules/path-platform": { - "version": "0.11.15", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/path-to-regexp": { - "version": "1.8.0", - "license": "MIT", - "dependencies": { - "isarray": "0.0.1" - } - }, - "node_modules/path-to-regexp/node_modules/isarray": { - "version": "0.0.1", - "license": "MIT" - }, - "node_modules/path-type": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/pathval": { - "version": "1.1.1", - "license": "MIT", - "engines": { - "node": "*" - } - }, - "node_modules/pbkdf2": { - "version": "3.1.2", - "dev": true, - "license": "MIT", - "dependencies": { - "create-hash": "^1.1.2", - "create-hmac": "^1.1.4", - "ripemd160": "^2.0.1", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - }, - "engines": { - "node": ">=0.12" - } - }, - "node_modules/peer-id": { - "version": "0.14.8", - "license": "MIT", - "dependencies": { - "cids": "^1.1.5", - "class-is": "^1.1.0", - "libp2p-crypto": "^0.19.0", - "minimist": "^1.2.5", - "multihashes": "^4.0.2", - "protobufjs": "^6.10.2", - "uint8arrays": "^2.0.5" - }, - "bin": { - "peer-id": "src/bin.js" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/peer-id/node_modules/uint8arrays": { - "version": "2.1.10", - "license": "MIT", - "dependencies": { - "multiformats": "^9.4.2" - } - }, - "node_modules/pem-jwk": { - "version": "2.0.0", - "license": "MPL-2.0", - "dependencies": { - "asn1.js": "^5.0.1" - }, - "bin": { - "pem-jwk": "bin/pem-jwk.js" - }, - "engines": { - "node": ">=5.10.0" - } - }, - "node_modules/perf-sym": { - "version": "2.0.3", - "dev": true, - "license": "MIT", - "dependencies": { - "end-of-stream": "^1.1.0", - "minimist": "^1.2.0", - "pump": "^1.0.1", - "resolve-jit-symbols": "^0.5.0", - "split2": "^2.0.1" - }, - "bin": { - "perf-sym": "cmd.js", - "profile_1ms.d": "profile_1ms.d" - } - }, - "node_modules/perf-sym/node_modules/pump": { - "version": "1.0.3", - "dev": true, - "license": "MIT", - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "node_modules/perf-sym/node_modules/split2": { - "version": "2.2.0", - "dev": true, - "license": "ISC", - "dependencies": { - "through2": "^2.0.2" - } - }, - "node_modules/performance-now": { - "version": "2.1.0", - "license": "MIT" - }, - "node_modules/picocolors": { - "version": "1.0.0", - "dev": true, - "license": "ISC" - }, - "node_modules/picomatch": { - "version": "2.3.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pidtree": { - "version": "0.6.0", - "dev": true, - "license": "MIT", - "bin": { - "pidtree": "bin/pidtree.js" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/pify": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/pinkie": { - "version": "2.0.4", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/pinkie-promise": { - "version": "2.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "pinkie": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/pino": { - "version": "5.17.0", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-redact": "^2.0.0", - "fast-safe-stringify": "^2.0.7", - "flatstr": "^1.0.12", - "pino-std-serializers": "^2.4.2", - "quick-format-unescaped": "^3.0.3", - "sonic-boom": "^0.7.5" - }, - "bin": { - "pino": "bin.js" - } - }, - "node_modules/pino-std-serializers": { - "version": "2.5.0", - "dev": true, - "license": "MIT" - }, - "node_modules/pkg-conf": { - "version": "2.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "find-up": "^2.0.0", - "load-json-file": "^4.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/pkg-conf/node_modules/find-up": { - "version": "2.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "locate-path": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/pkg-conf/node_modules/locate-path": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/pkg-conf/node_modules/p-limit": { - "version": "1.3.0", - "dev": true, - "license": "MIT", - "dependencies": { - "p-try": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/pkg-conf/node_modules/p-locate": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "p-limit": "^1.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/pkg-conf/node_modules/p-try": { - "version": "1.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/pkg-conf/node_modules/path-exists": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/pkg-config": { - "version": "1.1.1", - "dev": true, - "license": "MIT", - "dependencies": { - "debug-log": "^1.0.0", - "find-root": "^1.0.0", - "xtend": "^4.0.1" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/pkg-dir": { - "version": "4.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "find-up": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/find-up": { - "version": "4.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/locate-path": { - "version": "5.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/p-limit": { - "version": "2.3.0", - "dev": true, - "license": "MIT", - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/pkg-dir/node_modules/p-locate": { - "version": "4.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-up": { - "version": "1.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "find-up": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/pkg-up/node_modules/find-up": { - "version": "1.1.2", - "dev": true, - "license": "MIT", - "dependencies": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/pkg-up/node_modules/path-exists": { - "version": "2.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "pinkie-promise": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/platform": { - "version": "1.3.6", - "dev": true, - "license": "MIT" - }, - "node_modules/pluralize": { - "version": "1.2.1", - "dev": true, - "license": "MIT" - }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/prettier": { - "version": "2.7.1", - "dev": true, - "license": "MIT", - "bin": { - "prettier": "bin-prettier.js" - }, - "engines": { - "node": ">=10.13.0" - }, - "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" - } - }, - "node_modules/prettier-linter-helpers": { - "version": "1.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-diff": "^1.1.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/pretty-hrtime": { - "version": "1.0.3", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/pretty-trace": { - "version": "0.3.1", - "dev": true, - "license": "MIT", - "dependencies": { - "ansicolors": "~0.2.1", - "split2": "~0.2.1" - }, - "bin": { - "pretty-trace": "bin/pretty-trace" - } - }, - "node_modules/pretty-trace/node_modules/isarray": { - "version": "0.0.1", - "dev": true, - "license": "MIT" - }, - "node_modules/pretty-trace/node_modules/readable-stream": { - "version": "1.0.34", - "dev": true, - "license": "MIT", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "node_modules/pretty-trace/node_modules/split2": { - "version": "0.2.1", - "dev": true, - "license": "ISC", - "dependencies": { - "through2": "~0.6.1" - } - }, - "node_modules/pretty-trace/node_modules/string_decoder": { - "version": "0.10.31", - "dev": true, - "license": "MIT" - }, - "node_modules/pretty-trace/node_modules/through2": { - "version": "0.6.5", - "dev": true, - "license": "MIT", - "dependencies": { - "readable-stream": ">=1.0.33-1 <1.1.0-0", - "xtend": ">=4.0.0 <4.1.0-0" - } - }, - "node_modules/private-ip": { - "version": "2.3.4", - "license": "MIT", - "dependencies": { - "ip-regex": "^4.3.0", - "ipaddr.js": "^2.0.1", - "is-ip": "^3.1.0", - "netmask": "^2.0.2" - } - }, - "node_modules/process": { - "version": "0.11.10", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6.0" - } - }, - "node_modules/process-nextick-args": { - "version": "2.0.1", - "dev": true, - "license": "MIT" - }, - "node_modules/process-on-spawn": { - "version": "1.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "fromentries": "^1.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/progress": { - "version": "1.1.8", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/promise-to-callback": { - "version": "1.0.0", - "license": "MIT", - "dependencies": { - "is-fn": "^1.0.0", - "set-immediate-shim": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/protobufjs": { - "version": "6.11.3", - "hasInstallScript": true, - "license": "BSD-3-Clause", - "dependencies": { - "@protobufjs/aspromise": "^1.1.2", - "@protobufjs/base64": "^1.1.2", - "@protobufjs/codegen": "^2.0.4", - "@protobufjs/eventemitter": "^1.1.0", - "@protobufjs/fetch": "^1.1.0", - "@protobufjs/float": "^1.0.2", - "@protobufjs/inquire": "^1.1.0", - "@protobufjs/path": "^1.1.2", - "@protobufjs/pool": "^1.1.0", - "@protobufjs/utf8": "^1.1.0", - "@types/long": "^4.0.1", - "@types/node": ">=13.7.0", - "long": "^4.0.0" - }, - "bin": { - "pbjs": "bin/pbjs", - "pbts": "bin/pbts" - } - }, - "node_modules/protocol-buffers-schema": { - "version": "3.6.0", - "license": "MIT" - }, - "node_modules/protons": { - "version": "2.0.3", - "license": "MIT", - "dependencies": { - "protocol-buffers-schema": "^3.3.1", - "signed-varint": "^2.0.1", - "uint8arrays": "^3.0.0", - "varint": "^5.0.0" - } - }, - "node_modules/protons/node_modules/varint": { - "version": "5.0.2", - "license": "MIT" - }, - "node_modules/psl": { - "version": "1.9.0", - "license": "MIT" - }, - "node_modules/public-encrypt": { - "version": "4.0.3", - "dev": true, - "license": "MIT", - "dependencies": { - "bn.js": "^4.1.0", - "browserify-rsa": "^4.0.0", - "create-hash": "^1.1.0", - "parse-asn1": "^5.0.0", - "randombytes": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "node_modules/public-encrypt/node_modules/bn.js": { - "version": "4.12.0", - "dev": true, - "license": "MIT" - }, - "node_modules/pump": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "node_modules/pumpify": { - "version": "1.5.1", - "dev": true, - "license": "MIT", - "dependencies": { - "duplexify": "^3.6.0", - "inherits": "^2.0.3", - "pump": "^2.0.0" - } - }, - "node_modules/pumpify/node_modules/pump": { - "version": "2.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "node_modules/punycode": { - "version": "1.4.1", - "dev": true, - "license": "MIT" - }, - "node_modules/qheap": { - "version": "1.4.0", - "license": "Apache-2.0", - "engines": { - "node": "*" - } - }, - "node_modules/qjobs": { - "version": "1.2.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.9" - } - }, - "node_modules/qs": { - "version": "6.11.0", - "license": "BSD-3-Clause", - "dependencies": { - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/querystring": { - "version": "0.2.0", - "dev": true, - "engines": { - "node": ">=0.4.x" - } - }, - "node_modules/querystring-es3": { - "version": "0.2.1", - "dev": true, - "engines": { - "node": ">=0.4.x" - } - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/queue-tick": { - "version": "1.0.1", - "dev": true, - "license": "MIT" - }, - "node_modules/quibble": { - "version": "0.6.17", - "dev": true, - "license": "MIT", - "dependencies": { - "lodash": "^4.17.21", - "resolve": "^1.22.1" - }, - "engines": { - "node": ">= 0.14.0" - } - }, - "node_modules/quick-format-unescaped": { - "version": "3.0.3", - "dev": true, - "license": "MIT" - }, - "node_modules/randombytes": { - "version": "2.1.0", - "license": "MIT", - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "node_modules/randomfill": { - "version": "1.0.4", - "dev": true, - "license": "MIT", - "dependencies": { - "randombytes": "^2.0.5", - "safe-buffer": "^5.1.0" - } - }, - "node_modules/range-parser": { - "version": "1.2.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/raw-body": { - "version": "2.5.1", - "license": "MIT", - "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/react-native-fetch-api": { - "version": "2.0.0", - "license": "MIT", - "dependencies": { - "p-defer": "^3.0.0" - } - }, - "node_modules/read-only-stream": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "readable-stream": "^2.0.2" - } - }, - "node_modules/readable-stream": { - "version": "2.3.7", - "dev": true, - "license": "MIT", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/readable-stream/node_modules/safe-buffer": { - "version": "5.1.2", - "dev": true, - "license": "MIT" - }, - "node_modules/readable-stream/node_modules/string_decoder": { - "version": "1.1.1", - "dev": true, - "license": "MIT", - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/readdirp": { - "version": "3.6.0", - "dev": true, - "license": "MIT", - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/readline2": { - "version": "1.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "mute-stream": "0.0.5" - } - }, - "node_modules/readline2/node_modules/is-fullwidth-code-point": { - "version": "1.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "number-is-nan": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/receptacle": { - "version": "1.3.2", - "license": "MIT", - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/receptacle/node_modules/ms": { - "version": "2.1.3", - "license": "MIT" - }, - "node_modules/rechoir": { - "version": "0.7.1", - "dev": true, - "license": "MIT", - "dependencies": { - "resolve": "^1.9.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/regenerate": { - "version": "1.4.2", - "dev": true, - "license": "MIT" - }, - "node_modules/regenerate-unicode-properties": { - "version": "10.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "regenerate": "^1.4.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/regenerator-runtime": { - "version": "0.13.10", - "dev": true, - "license": "MIT" - }, - "node_modules/regenerator-transform": { - "version": "0.15.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.8.4" - } - }, - "node_modules/regexp.prototype.flags": { - "version": "1.4.3", - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "functions-have-names": "^1.2.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/regexpp": { - "version": "3.2.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - } - }, - "node_modules/regexpu-core": { - "version": "5.2.1", - "dev": true, - "license": "MIT", - "dependencies": { - "regenerate": "^1.4.2", - "regenerate-unicode-properties": "^10.1.0", - "regjsgen": "^0.7.1", - "regjsparser": "^0.9.1", - "unicode-match-property-ecmascript": "^2.0.0", - "unicode-match-property-value-ecmascript": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/regjsgen": { - "version": "0.7.1", - "dev": true, - "license": "MIT" - }, - "node_modules/regjsparser": { - "version": "0.9.1", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "jsesc": "~0.5.0" - }, - "bin": { - "regjsparser": "bin/parser" - } - }, - "node_modules/regjsparser/node_modules/jsesc": { - "version": "0.5.0", - "dev": true, - "bin": { - "jsesc": "bin/jsesc" - } - }, - "node_modules/release-zalgo": { - "version": "1.0.0", - "dev": true, - "license": "ISC", - "dependencies": { - "es6-error": "^4.0.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/request": { - "version": "2.88.2", - "license": "Apache-2.0", - "dependencies": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.3", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.5.0", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/request/node_modules/qs": { - "version": "6.5.3", - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.6" - } - }, - "node_modules/request/node_modules/uuid": { - "version": "3.4.0", - "license": "MIT", - "bin": { - "uuid": "bin/uuid" - } - }, - "node_modules/require-directory": { - "version": "2.1.1", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/require-main-filename": { - "version": "2.0.0", - "dev": true, - "license": "ISC" - }, - "node_modules/require-uncached": { - "version": "1.0.3", - "dev": true, - "license": "MIT", - "dependencies": { - "caller-path": "^0.1.0", - "resolve-from": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/require-uncached/node_modules/resolve-from": { - "version": "1.0.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/requires-port": { - "version": "1.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/resolve": { - "version": "1.22.1", - "dev": true, - "license": "MIT", - "dependencies": { - "is-core-module": "^2.9.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/resolve-cwd": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/resolve-cwd/node_modules/resolve-from": { - "version": "5.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/resolve-from": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/resolve-jit-symbols": { - "version": "0.5.0", - "dev": true, - "license": "MIT", - "dependencies": { - "pretty-trace": "~0.3.1" - }, - "bin": { - "rjs": "bin/rjs" - } - }, - "node_modules/restore-cursor": { - "version": "3.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/resumer": { - "version": "0.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "through": "~2.3.4" - } - }, - "node_modules/retimer": { - "version": "2.0.0", - "license": "MIT" - }, - "node_modules/retry": { - "version": "0.13.1", - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/reusify": { - "version": "1.0.4", - "dev": true, - "license": "MIT", - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rfdc": { - "version": "1.3.0", - "dev": true, - "license": "MIT" - }, - "node_modules/rimraf": { - "version": "3.0.2", - "dev": true, - "license": "ISC", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/ripemd160": { - "version": "2.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1" - } - }, - "node_modules/run-async": { - "version": "0.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "once": "^1.3.0" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/run-parallel-limit": { - "version": "1.1.0", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/rustbn.js": { - "version": "0.2.0", - "license": "(MIT OR Apache-2.0)" - }, - "node_modules/rx-lite": { - "version": "3.1.2", - "dev": true - }, - "node_modules/rxjs": { - "version": "7.5.7", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.1.0" - } - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/safe-regex-test": { - "version": "1.0.0", - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", - "is-regex": "^1.1.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/safe-stable-stringify": { - "version": "2.4.1", - "license": "MIT", - "engines": { - "node": ">=10" - } - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "license": "MIT" - }, - "node_modules/sanitize-filename": { - "version": "1.6.3", - "license": "WTFPL OR ISC", - "dependencies": { - "truncate-utf8-bytes": "^1.0.0" - } - }, - "node_modules/sax": { - "version": "1.2.4", - "license": "ISC" - }, - "node_modules/scanf": { - "version": "1.1.2", - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/schema-utils": { - "version": "2.7.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/json-schema": "^7.0.5", - "ajv": "^6.12.4", - "ajv-keywords": "^3.5.2" - }, - "engines": { - "node": ">= 8.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/scrypt-js": { - "version": "3.0.1", - "license": "MIT" - }, - "node_modules/secp256k1": { - "version": "4.0.3", - "hasInstallScript": true, - "license": "MIT", - "dependencies": { - "elliptic": "^6.5.4", - "node-addon-api": "^2.0.0", - "node-gyp-build": "^4.2.0" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/secp256k1/node_modules/node-addon-api": { - "version": "2.0.2", - "license": "MIT" - }, - "node_modules/semver": { - "version": "7.3.8", - "dev": true, - "license": "ISC", - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/semver/node_modules/lru-cache": { - "version": "6.0.0", - "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/semver/node_modules/yallist": { - "version": "4.0.0", - "dev": true, - "license": "ISC" - }, - "node_modules/serialize-javascript": { - "version": "6.0.0", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "randombytes": "^2.1.0" - } - }, - "node_modules/set-blocking": { - "version": "2.0.0", - "dev": true, - "license": "ISC" - }, - "node_modules/set-delayed-interval": { - "version": "1.0.0", - "license": "MIT" - }, - "node_modules/set-immediate-shim": { - "version": "1.0.1", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/setimmediate": { - "version": "1.0.5", - "dev": true, - "license": "MIT" - }, - "node_modules/setprototypeof": { - "version": "1.2.0", - "license": "ISC" - }, - "node_modules/sha.js": { - "version": "2.4.11", - "dev": true, - "license": "(MIT AND BSD-3-Clause)", - "dependencies": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - }, - "bin": { - "sha.js": "bin.js" - } - }, - "node_modules/shallow-clone": { - "version": "3.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "kind-of": "^6.0.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shasum": { - "version": "1.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "json-stable-stringify": "~0.0.0", - "sha.js": "~2.4.4" - } - }, - "node_modules/shasum-object": { - "version": "1.0.0", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "fast-safe-stringify": "^2.0.7" - } - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "license": "MIT", - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/shell-quote": { - "version": "1.7.4", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/shelljs": { - "version": "0.7.8", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "glob": "^7.0.0", - "interpret": "^1.0.0", - "rechoir": "^0.6.2" - }, - "bin": { - "shjs": "bin/shjs" - }, - "engines": { - "iojs": "*", - "node": ">=0.11.0" - } - }, - "node_modules/shelljs/node_modules/interpret": { - "version": "1.4.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/shelljs/node_modules/rechoir": { - "version": "0.6.2", - "dev": true, - "dependencies": { - "resolve": "^1.1.6" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/shiki": { - "version": "0.10.1", - "dev": true, - "license": "MIT", - "dependencies": { - "jsonc-parser": "^3.0.0", - "vscode-oniguruma": "^1.6.1", - "vscode-textmate": "5.2.0" - } - }, - "node_modules/side-channel": { - "version": "1.0.4", - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/signal-exit": { - "version": "3.0.7", - "license": "ISC" - }, - "node_modules/signed-varint": { - "version": "2.0.1", - "license": "MIT", - "dependencies": { - "varint": "~5.0.0" - } - }, - "node_modules/signed-varint/node_modules/varint": { - "version": "5.0.2", - "license": "MIT" - }, - "node_modules/simple-concat": { - "version": "1.0.1", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/simple-swizzle": { - "version": "0.2.2", - "license": "MIT", - "dependencies": { - "is-arrayish": "^0.3.1" - } - }, - "node_modules/simple-swizzle/node_modules/is-arrayish": { - "version": "0.3.2", - "license": "MIT" - }, - "node_modules/single-line-log": { - "version": "1.1.2", - "dev": true, - "license": "MIT", - "dependencies": { - "string-width": "^1.0.1" - } - }, - "node_modules/single-line-log/node_modules/ansi-regex": { - "version": "2.1.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/single-line-log/node_modules/is-fullwidth-code-point": { - "version": "1.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "number-is-nan": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/single-line-log/node_modules/string-width": { - "version": "1.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/single-line-log/node_modules/strip-ansi": { - "version": "3.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sinon": { - "version": "9.2.4", - "license": "BSD-3-Clause", - "dependencies": { - "@sinonjs/commons": "^1.8.1", - "@sinonjs/fake-timers": "^6.0.1", - "@sinonjs/samsam": "^5.3.1", - "diff": "^4.0.2", - "nise": "^4.0.4", - "supports-color": "^7.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/sinon" - } - }, - "node_modules/slash": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/slice-ansi": { - "version": "5.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^6.0.0", - "is-fullwidth-code-point": "^4.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" - } - }, - "node_modules/slice-ansi/node_modules/ansi-styles": { - "version": "6.2.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/snappyjs": { - "version": "0.6.1", - "license": "MIT" - }, - "node_modules/socket.io": { - "version": "4.5.3", - "dev": true, - "license": "MIT", - "dependencies": { - "accepts": "~1.3.4", - "base64id": "~2.0.0", - "debug": "~4.3.2", - "engine.io": "~6.2.0", - "socket.io-adapter": "~2.4.0", - "socket.io-parser": "~4.2.0" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/socket.io-adapter": { - "version": "2.4.0", - "dev": true, - "license": "MIT" - }, - "node_modules/socket.io-parser": { - "version": "4.2.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@socket.io/component-emitter": "~3.1.0", - "debug": "~4.3.1" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/solc": { - "version": "0.8.17", - "dev": true, - "license": "MIT", - "dependencies": { - "command-exists": "^1.2.8", - "commander": "^8.1.0", - "follow-redirects": "^1.12.1", - "js-sha3": "0.8.0", - "memorystream": "^0.3.1", - "semver": "^5.5.0", - "tmp": "0.0.33" - }, - "bin": { - "solcjs": "solc.js" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/solc/node_modules/commander": { - "version": "8.3.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 12" - } - }, - "node_modules/solc/node_modules/semver": { - "version": "5.7.1", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/solc/node_modules/tmp": { - "version": "0.0.33", - "dev": true, - "license": "MIT", - "dependencies": { - "os-tmpdir": "~1.0.2" - }, - "engines": { - "node": ">=0.6.0" - } - }, - "node_modules/sonic-boom": { - "version": "0.7.7", - "dev": true, - "license": "MIT", - "dependencies": { - "atomic-sleep": "^1.0.0", - "flatstr": "^1.0.12" - } - }, - "node_modules/sort-object-keys": { - "version": "1.1.3", - "dev": true, - "license": "MIT" - }, - "node_modules/sort-package-json": { - "version": "1.57.0", - "dev": true, - "license": "MIT", - "dependencies": { - "detect-indent": "^6.0.0", - "detect-newline": "3.1.0", - "git-hooks-list": "1.0.3", - "globby": "10.0.0", - "is-plain-obj": "2.1.0", - "sort-object-keys": "^1.1.3" - }, - "bin": { - "sort-package-json": "cli.js" - } - }, - "node_modules/sort-package-json/node_modules/globby": { - "version": "10.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/glob": "^7.1.1", - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.0.3", - "glob": "^7.1.3", - "ignore": "^5.1.1", - "merge2": "^1.2.3", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/source-map": { - "version": "0.5.7", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-support": { - "version": "0.5.21", - "dev": true, - "license": "MIT", - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/source-map-support/node_modules/source-map": { - "version": "0.6.1", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sourcemap-codec": { - "version": "1.4.8", - "dev": true, - "license": "MIT" - }, - "node_modules/spawn-wrap": { - "version": "2.0.0", - "dev": true, - "license": "ISC", - "dependencies": { - "foreground-child": "^2.0.0", - "is-windows": "^1.0.2", - "make-dir": "^3.0.0", - "rimraf": "^3.0.0", - "signal-exit": "^3.0.2", - "which": "^2.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/spawn-wrap/node_modules/make-dir": { - "version": "3.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "semver": "^6.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/spawn-wrap/node_modules/semver": { - "version": "6.3.0", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/spawn-wrap/node_modules/which": { - "version": "2.0.2", - "dev": true, - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/split2": { - "version": "3.2.2", - "dev": true, - "license": "ISC", - "dependencies": { - "readable-stream": "^3.0.0" - } - }, - "node_modules/split2/node_modules/readable-stream": { - "version": "3.6.0", - "dev": true, - "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/sprintf-js": { - "version": "1.1.2", - "license": "BSD-3-Clause" - }, - "node_modules/sshpk": { - "version": "1.17.0", - "license": "MIT", - "dependencies": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - }, - "bin": { - "sshpk-conv": "bin/sshpk-conv", - "sshpk-sign": "bin/sshpk-sign", - "sshpk-verify": "bin/sshpk-verify" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sshpk/node_modules/jsbn": { - "version": "0.1.1", - "license": "MIT" - }, - "node_modules/stack-trace": { - "version": "0.0.10", - "license": "MIT", - "engines": { - "node": "*" - } - }, - "node_modules/standard": { - "version": "10.0.3", - "dev": true, - "license": "MIT", - "dependencies": { - "eslint": "~3.19.0", - "eslint-config-standard": "10.2.1", - "eslint-config-standard-jsx": "4.0.2", - "eslint-plugin-import": "~2.2.0", - "eslint-plugin-node": "~4.2.2", - "eslint-plugin-promise": "~3.5.0", - "eslint-plugin-react": "~6.10.0", - "eslint-plugin-standard": "~3.0.1", - "standard-engine": "~7.0.0" - }, - "bin": { - "standard": "bin/cmd.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/standard-engine": { - "version": "7.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "deglob": "^2.1.0", - "get-stdin": "^5.0.1", - "minimist": "^1.1.0", - "pkg-conf": "^2.0.0" - } - }, - "node_modules/standard/node_modules/acorn": { - "version": "5.7.4", - "dev": true, - "license": "MIT", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/standard/node_modules/acorn-jsx": { - "version": "3.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "acorn": "^3.0.4" - } - }, - "node_modules/standard/node_modules/acorn-jsx/node_modules/acorn": { - "version": "3.3.0", - "dev": true, - "license": "MIT", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/standard/node_modules/ansi-regex": { - "version": "2.1.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/standard/node_modules/ansi-styles": { - "version": "2.2.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/standard/node_modules/argparse": { - "version": "1.0.10", - "dev": true, - "license": "MIT", - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/standard/node_modules/chalk": { - "version": "1.1.3", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/standard/node_modules/debug": { - "version": "2.6.9", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/standard/node_modules/doctrine": { - "version": "2.1.0", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/standard/node_modules/eslint": { - "version": "3.19.0", - "dev": true, - "license": "MIT", - "dependencies": { - "babel-code-frame": "^6.16.0", - "chalk": "^1.1.3", - "concat-stream": "^1.5.2", - "debug": "^2.1.1", - "doctrine": "^2.0.0", - "escope": "^3.6.0", - "espree": "^3.4.0", - "esquery": "^1.0.0", - "estraverse": "^4.2.0", - "esutils": "^2.0.2", - "file-entry-cache": "^2.0.0", - "glob": "^7.0.3", - "globals": "^9.14.0", - "ignore": "^3.2.0", - "imurmurhash": "^0.1.4", - "inquirer": "^0.12.0", - "is-my-json-valid": "^2.10.0", - "is-resolvable": "^1.0.0", - "js-yaml": "^3.5.1", - "json-stable-stringify": "^1.0.0", - "levn": "^0.3.0", - "lodash": "^4.0.0", - "mkdirp": "^0.5.0", - "natural-compare": "^1.4.0", - "optionator": "^0.8.2", - "path-is-inside": "^1.0.1", - "pluralize": "^1.2.1", - "progress": "^1.1.8", - "require-uncached": "^1.0.2", - "shelljs": "^0.7.5", - "strip-bom": "^3.0.0", - "strip-json-comments": "~2.0.1", - "table": "^3.7.8", - "text-table": "~0.2.0", - "user-home": "^2.0.0" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/standard/node_modules/eslint-config-standard-jsx": { - "version": "4.0.2", - "dev": true, - "license": "MIT", - "peerDependencies": { - "eslint": ">=3.19.0", - "eslint-plugin-react": ">=6.10.3" - } - }, - "node_modules/standard/node_modules/eslint-import-resolver-node": { - "version": "0.2.3", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^2.2.0", - "object-assign": "^4.0.1", - "resolve": "^1.1.6" - } - }, - "node_modules/standard/node_modules/eslint-plugin-import": { - "version": "2.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "builtin-modules": "^1.1.1", - "contains-path": "^0.1.0", - "debug": "^2.2.0", - "doctrine": "1.5.0", - "eslint-import-resolver-node": "^0.2.0", - "eslint-module-utils": "^2.0.0", - "has": "^1.0.1", - "lodash.cond": "^4.3.0", - "minimatch": "^3.0.3", - "pkg-up": "^1.0.0" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": "2.x - 3.x" - } - }, - "node_modules/standard/node_modules/eslint-plugin-import/node_modules/doctrine": { - "version": "1.5.0", - "dev": true, - "dependencies": { - "esutils": "^2.0.2", - "isarray": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/standard/node_modules/eslint-plugin-react": { - "version": "6.10.3", - "dev": true, - "license": "MIT", - "dependencies": { - "array.prototype.find": "^2.0.1", - "doctrine": "^1.2.2", - "has": "^1.0.1", - "jsx-ast-utils": "^1.3.4", - "object.assign": "^4.0.4" - }, - "engines": { - "node": ">=0.10" - }, - "peerDependencies": { - "eslint": "^2.0.0 || ^3.0.0" - } - }, - "node_modules/standard/node_modules/eslint-plugin-react/node_modules/doctrine": { - "version": "1.5.0", - "dev": true, - "dependencies": { - "esutils": "^2.0.2", - "isarray": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/standard/node_modules/espree": { - "version": "3.5.4", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "acorn": "^5.5.0", - "acorn-jsx": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/standard/node_modules/file-entry-cache": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "flat-cache": "^1.2.1", - "object-assign": "^4.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/standard/node_modules/flat-cache": { - "version": "1.3.4", - "dev": true, - "license": "MIT", - "dependencies": { - "circular-json": "^0.3.1", - "graceful-fs": "^4.1.2", - "rimraf": "~2.6.2", - "write": "^0.2.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/standard/node_modules/globals": { - "version": "9.18.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/standard/node_modules/ignore": { - "version": "3.3.10", - "dev": true, - "license": "MIT" - }, - "node_modules/standard/node_modules/js-yaml": { - "version": "3.14.1", - "dev": true, - "license": "MIT", - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/standard/node_modules/json-stable-stringify": { - "version": "1.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "jsonify": "~0.0.0" - } - }, - "node_modules/standard/node_modules/jsx-ast-utils": { - "version": "1.4.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/standard/node_modules/levn": { - "version": "0.3.0", - "dev": true, - "license": "MIT", - "dependencies": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/standard/node_modules/ms": { - "version": "2.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/standard/node_modules/optionator": { - "version": "0.8.3", - "dev": true, - "license": "MIT", - "dependencies": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.6", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "word-wrap": "~1.2.3" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/standard/node_modules/prelude-ls": { - "version": "1.1.2", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/standard/node_modules/rimraf": { - "version": "2.6.3", - "dev": true, - "license": "ISC", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, - "node_modules/standard/node_modules/sprintf-js": { - "version": "1.0.3", - "dev": true, - "license": "BSD-3-Clause" - }, - "node_modules/standard/node_modules/strip-ansi": { - "version": "3.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/standard/node_modules/strip-bom": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/standard/node_modules/strip-json-comments": { - "version": "2.0.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/standard/node_modules/supports-color": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/standard/node_modules/type-check": { - "version": "0.3.2", - "dev": true, - "license": "MIT", - "dependencies": { - "prelude-ls": "~1.1.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/statuses": { - "version": "1.5.0", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/stream-browserify": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "inherits": "~2.0.4", - "readable-stream": "^3.5.0" - } - }, - "node_modules/stream-browserify/node_modules/readable-stream": { - "version": "3.6.0", - "dev": true, - "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/stream-combiner2": { - "version": "1.1.1", - "dev": true, - "license": "MIT", - "dependencies": { - "duplexer2": "~0.1.0", - "readable-stream": "^2.0.2" - } - }, - "node_modules/stream-http": { - "version": "3.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "builtin-status-codes": "^3.0.0", - "inherits": "^2.0.4", - "readable-stream": "^3.6.0", - "xtend": "^4.0.2" - } - }, - "node_modules/stream-http/node_modules/readable-stream": { - "version": "3.6.0", - "dev": true, - "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/stream-shift": { - "version": "1.0.1", - "dev": true, - "license": "MIT" - }, - "node_modules/stream-splicer": { - "version": "2.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "inherits": "^2.0.1", - "readable-stream": "^2.0.2" - } - }, - "node_modules/stream-to-it": { - "version": "0.2.4", - "license": "MIT", - "dependencies": { - "get-iterator": "^1.0.2" - } - }, - "node_modules/streaming-iterables": { - "version": "5.0.4", - "license": "MIT", - "engines": { - "node": ">=10" - } - }, - "node_modules/streamroller": { - "version": "3.1.3", - "dev": true, - "license": "MIT", - "dependencies": { - "date-format": "^4.0.14", - "debug": "^4.3.4", - "fs-extra": "^8.1.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/streamroller/node_modules/fs-extra": { - "version": "8.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - }, - "engines": { - "node": ">=6 <7 || >=8" - } - }, - "node_modules/streamroller/node_modules/jsonfile": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/streamroller/node_modules/universalify": { - "version": "0.1.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/string_decoder": { - "version": "1.3.0", - "license": "MIT", - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "node_modules/string-argv": { - "version": "0.3.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.6.19" - } - }, - "node_modules/string-width": { - "version": "5.1.2", - "dev": true, - "license": "MIT", - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/string-width/node_modules/ansi-regex": { - "version": "6.0.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/string-width/node_modules/strip-ansi": { - "version": "7.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/string.prototype.trim": { - "version": "1.2.6", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.19.5" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimend": { - "version": "1.0.5", - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.19.5" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimstart": { - "version": "1.0.5", - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.19.5" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/stringify-object-es5": { - "version": "2.5.0", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "is-plain-obj": "^1.0.0", - "is-regexp": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/stringify-object-es5/node_modules/is-plain-obj": { - "version": "1.1.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-bom": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-final-newline": { - "version": "2.0.0", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/subarg": { - "version": "1.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "minimist": "^1.1.0" - } - }, - "node_modules/superagent": { - "version": "8.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "component-emitter": "^1.3.0", - "cookiejar": "^2.1.3", - "debug": "^4.3.4", - "fast-safe-stringify": "^2.1.1", - "form-data": "^4.0.0", - "formidable": "^2.0.1", - "methods": "^1.1.2", - "mime": "2.6.0", - "qs": "^6.11.0", - "semver": "^7.3.7" - }, - "engines": { - "node": ">=6.4.0 <13 || >=14" - } - }, - "node_modules/superagent/node_modules/form-data": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/supertest": { - "version": "6.3.0", - "dev": true, - "license": "MIT", - "dependencies": { - "methods": "^1.1.2", - "superagent": "^8.0.0" - }, - "engines": { - "node": ">=6.4.0" - } - }, - "node_modules/superwstest": { - "version": "2.0.3", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/supertest": "<7", - "@types/ws": "7.x || 8.x", - "ws": "7.x || 8.x" - }, - "peerDependencies": { - "supertest": "*" - }, - "peerDependenciesMeta": { - "supertest": { - "optional": true - } - } - }, - "node_modules/supports-color": { - "version": "7.2.0", - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/svg-element-attributes": { - "version": "1.3.1", - "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/syntax-error": { - "version": "1.4.0", - "dev": true, - "license": "MIT", - "dependencies": { - "acorn-node": "^1.2.0" - } - }, - "node_modules/table": { - "version": "3.8.3", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "ajv": "^4.7.0", - "ajv-keywords": "^1.0.0", - "chalk": "^1.1.1", - "lodash": "^4.0.0", - "slice-ansi": "0.0.4", - "string-width": "^2.0.0" - } - }, - "node_modules/table/node_modules/ajv": { - "version": "4.11.8", - "dev": true, - "license": "MIT", - "dependencies": { - "co": "^4.6.0", - "json-stable-stringify": "^1.0.1" - } - }, - "node_modules/table/node_modules/ajv-keywords": { - "version": "1.5.1", - "dev": true, - "license": "MIT", - "peerDependencies": { - "ajv": ">=4.10.0" - } - }, - "node_modules/table/node_modules/ansi-regex": { - "version": "2.1.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/table/node_modules/ansi-styles": { - "version": "2.2.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/table/node_modules/chalk": { - "version": "1.1.3", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/table/node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/table/node_modules/json-stable-stringify": { - "version": "1.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "jsonify": "~0.0.0" - } - }, - "node_modules/table/node_modules/slice-ansi": { - "version": "0.0.4", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/table/node_modules/string-width": { - "version": "2.1.1", - "dev": true, - "license": "MIT", - "dependencies": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/table/node_modules/string-width/node_modules/ansi-regex": { - "version": "3.0.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/table/node_modules/string-width/node_modules/strip-ansi": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/table/node_modules/strip-ansi": { - "version": "3.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/table/node_modules/supports-color": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/tachyons": { - "version": "4.12.0", - "dev": true, - "license": "MIT" - }, - "node_modules/tapable": { - "version": "2.2.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/tape": { - "version": "5.6.0", - "dev": true, - "license": "MIT", - "dependencies": { - "array.prototype.every": "^1.1.3", - "call-bind": "^1.0.2", - "deep-equal": "^2.0.5", - "defined": "^1.0.0", - "dotignore": "^0.1.2", - "for-each": "^0.3.3", - "get-package-type": "^0.1.0", - "glob": "^7.2.3", - "has": "^1.0.3", - "has-dynamic-import": "^2.0.1", - "inherits": "^2.0.4", - "is-regex": "^1.1.4", - "minimist": "^1.2.6", - "object-inspect": "^1.12.2", - "object-is": "^1.1.5", - "object-keys": "^1.1.1", - "object.assign": "^4.1.3", - "resolve": "^2.0.0-next.3", - "resumer": "^0.0.0", - "string.prototype.trim": "^1.2.6", - "through": "^2.3.8" - }, - "bin": { - "tape": "bin/tape" - } - }, - "node_modules/tape/node_modules/resolve": { - "version": "2.0.0-next.4", - "dev": true, - "license": "MIT", - "dependencies": { - "is-core-module": "^2.9.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/terser": { - "version": "5.15.1", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "@jridgewell/source-map": "^0.3.2", - "acorn": "^8.5.0", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - }, - "bin": { - "terser": "bin/terser" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/terser-webpack-plugin": { - "version": "5.3.6", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.14", - "jest-worker": "^27.4.5", - "schema-utils": "^3.1.1", - "serialize-javascript": "^6.0.0", - "terser": "^5.14.1" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.1.0" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "esbuild": { - "optional": true - }, - "uglify-js": { - "optional": true - } - } - }, - "node_modules/terser-webpack-plugin/node_modules/schema-utils": { - "version": "3.1.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/terser/node_modules/commander": { - "version": "2.20.3", - "dev": true, - "license": "MIT" - }, - "node_modules/test-exclude": { - "version": "6.0.0", - "dev": true, - "license": "ISC", - "dependencies": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/testdouble": { - "version": "3.17.2", - "dev": true, - "license": "MIT", - "dependencies": { - "lodash": "^4.17.21", - "quibble": "^0.6.17", - "stringify-object-es5": "^2.5.0", - "theredoc": "^1.0.0" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/testdouble-timers": { - "version": "0.1.1", - "dev": true, - "license": "MIT", - "dependencies": { - "lolex": "^1.4.0" - }, - "peerDependencies": { - "testdouble": "^3.0.0" - } - }, - "node_modules/text-hex": { - "version": "1.0.0", - "license": "MIT" - }, - "node_modules/text-table": { - "version": "0.2.0", - "dev": true, - "license": "MIT" - }, - "node_modules/theredoc": { - "version": "1.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/through": { - "version": "2.3.8", - "license": "MIT" - }, - "node_modules/through2": { - "version": "2.0.5", - "dev": true, - "license": "MIT", - "dependencies": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } - }, - "node_modules/timeout-abort-controller": { - "version": "1.1.1", - "license": "MIT", - "dependencies": { - "abort-controller": "^3.0.0", - "retimer": "^2.0.0" - } - }, - "node_modules/timers-browserify": { - "version": "1.4.2", - "dev": true, - "dependencies": { - "process": "~0.11.0" - }, - "engines": { - "node": ">=0.6.0" - } - }, - "node_modules/tmp": { - "version": "0.2.1", - "dev": true, - "license": "MIT", - "dependencies": { - "rimraf": "^3.0.0" - }, - "engines": { - "node": ">=8.17.0" - } - }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/toidentifier": { - "version": "1.0.1", - "license": "MIT", - "engines": { - "node": ">=0.6" - } - }, - "node_modules/tough-cookie": { - "version": "2.5.0", - "license": "BSD-3-Clause", - "dependencies": { - "psl": "^1.1.28", - "punycode": "^2.1.1" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/tough-cookie/node_modules/punycode": { - "version": "2.1.1", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/tr46": { - "version": "0.0.3", - "license": "MIT" - }, - "node_modules/transform-ast": { - "version": "2.4.4", - "dev": true, - "license": "MIT", - "dependencies": { - "acorn-node": "^1.3.0", - "convert-source-map": "^1.5.1", - "dash-ast": "^1.0.0", - "is-buffer": "^2.0.0", - "magic-string": "^0.23.2", - "merge-source-map": "1.0.4", - "nanobench": "^2.1.1" - } - }, - "node_modules/transform-ast/node_modules/convert-source-map": { - "version": "1.9.0", - "dev": true, - "license": "MIT" - }, - "node_modules/transform-ast/node_modules/magic-string": { - "version": "0.23.2", - "dev": true, - "license": "MIT", - "dependencies": { - "sourcemap-codec": "^1.4.1" - } - }, - "node_modules/triple-beam": { - "version": "1.3.0", - "license": "MIT" - }, - "node_modules/truncate-utf8-bytes": { - "version": "1.0.2", - "license": "WTFPL", - "dependencies": { - "utf8-byte-length": "^1.0.1" - } - }, - "node_modules/ts-node": { - "version": "10.9.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@cspotcode/source-map-support": "^0.8.0", - "@tsconfig/node10": "^1.0.7", - "@tsconfig/node12": "^1.0.7", - "@tsconfig/node14": "^1.0.0", - "@tsconfig/node16": "^1.0.2", - "acorn": "^8.4.1", - "acorn-walk": "^8.1.1", - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.1", - "yn": "3.1.1" - }, - "bin": { - "ts-node": "dist/bin.js", - "ts-node-cwd": "dist/bin-cwd.js", - "ts-node-esm": "dist/bin-esm.js", - "ts-node-script": "dist/bin-script.js", - "ts-node-transpile-only": "dist/bin-transpile.js", - "ts-script": "dist/bin-script-deprecated.js" - }, - "peerDependencies": { - "@swc/core": ">=1.2.50", - "@swc/wasm": ">=1.2.50", - "@types/node": "*", - "typescript": ">=2.7" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "@swc/wasm": { - "optional": true - } - } - }, - "node_modules/ts-node/node_modules/acorn-walk": { - "version": "8.2.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/tsconfig-paths": { - "version": "3.14.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/json5": "^0.0.29", - "json5": "^1.0.1", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" - } - }, - "node_modules/tsconfig-paths/node_modules/json5": { - "version": "1.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "minimist": "^1.2.0" - }, - "bin": { - "json5": "lib/cli.js" - } - }, - "node_modules/tsconfig-paths/node_modules/strip-bom": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/tslib": { - "version": "2.4.0", - "dev": true, - "license": "0BSD" - }, - "node_modules/tsutils": { - "version": "3.21.0", - "dev": true, - "license": "MIT", - "dependencies": { - "tslib": "^1.8.1" - }, - "engines": { - "node": ">= 6" - }, - "peerDependencies": { - "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" - } - }, - "node_modules/tsutils/node_modules/tslib": { - "version": "1.14.1", - "dev": true, - "license": "0BSD" - }, - "node_modules/tty-browserify": { - "version": "0.0.1", - "dev": true, - "license": "MIT" - }, - "node_modules/tunnel-agent": { - "version": "0.6.0", - "license": "Apache-2.0", - "dependencies": { - "safe-buffer": "^5.0.1" - }, - "engines": { - "node": "*" - } - }, - "node_modules/tweetnacl": { - "version": "0.14.5", - "license": "Unlicense" - }, - "node_modules/type": { - "version": "1.2.0", - "dev": true, - "license": "ISC" - }, - "node_modules/type-check": { - "version": "0.4.0", - "dev": true, - "license": "MIT", - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/type-component": { - "version": "0.0.1", - "dev": true - }, - "node_modules/type-detect": { - "version": "4.0.8", - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/type-fest": { - "version": "0.20.2", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/type-is": { - "version": "1.6.18", - "license": "MIT", - "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/typedarray": { - "version": "0.0.6", - "dev": true, - "license": "MIT" - }, - "node_modules/typedarray-to-buffer": { - "version": "3.1.5", - "dev": true, - "license": "MIT", - "dependencies": { - "is-typedarray": "^1.0.0" - } - }, - "node_modules/typedoc": { - "version": "0.23.10", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "lunr": "^2.3.9", - "marked": "^4.0.18", - "minimatch": "^5.1.0", - "shiki": "^0.10.1" - }, - "bin": { - "typedoc": "bin/typedoc" - }, - "engines": { - "node": ">= 14.14" - }, - "peerDependencies": { - "typescript": "4.6.x || 4.7.x" - } - }, - "node_modules/typedoc-plugin-markdown": { - "version": "3.13.4", - "dev": true, - "license": "MIT", - "dependencies": { - "handlebars": "^4.7.7" - }, - "peerDependencies": { - "typedoc": ">=0.23.0" - } - }, - "node_modules/typedoc/node_modules/brace-expansion": { - "version": "2.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/typedoc/node_modules/minimatch": { - "version": "5.1.0", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/typescript": { - "version": "4.7.4", - "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=4.2.0" - } - }, - "node_modules/ua-parser-js": { - "version": "0.7.32", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/ua-parser-js" - }, - { - "type": "paypal", - "url": "https://paypal.me/faisalman" - } - ], - "license": "MIT", - "engines": { - "node": "*" - } - }, - "node_modules/uglify-js": { - "version": "3.17.3", - "dev": true, - "license": "BSD-2-Clause", - "optional": true, - "bin": { - "uglifyjs": "bin/uglifyjs" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/uint8arrays": { - "version": "3.1.1", - "license": "MIT", - "dependencies": { - "multiformats": "^9.4.2" - } - }, - "node_modules/umd": { - "version": "3.0.3", - "dev": true, - "license": "MIT", - "bin": { - "umd": "bin/cli.js" - } - }, - "node_modules/unbox-primitive": { - "version": "1.0.2", - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "has-bigints": "^1.0.2", - "has-symbols": "^1.0.3", - "which-boxed-primitive": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/undeclared-identifiers": { - "version": "1.1.3", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "acorn-node": "^1.3.0", - "dash-ast": "^1.0.0", - "get-assigned-identifiers": "^1.2.0", - "simple-concat": "^1.0.0", - "xtend": "^4.0.1" - }, - "bin": { - "undeclared-identifiers": "bin.js" - } - }, - "node_modules/unicode-canonical-property-names-ecmascript": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/unicode-match-property-ecmascript": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "unicode-canonical-property-names-ecmascript": "^2.0.0", - "unicode-property-aliases-ecmascript": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/unicode-match-property-value-ecmascript": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/unicode-property-aliases-ecmascript": { - "version": "2.1.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/uniq": { - "version": "1.0.1", - "dev": true, - "license": "MIT" - }, - "node_modules/universalify": { - "version": "2.0.0", - "license": "MIT", - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/unordered-array-remove": { - "version": "1.0.2", - "license": "MIT" - }, - "node_modules/unpipe": { - "version": "1.0.0", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/update-browserslist-db": { - "version": "1.0.10", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - } - ], - "license": "MIT", - "dependencies": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" - }, - "bin": { - "browserslist-lint": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, - "node_modules/upper-case": { - "version": "1.1.3", - "dev": true, - "license": "MIT" - }, - "node_modules/uri-js": { - "version": "4.4.1", - "license": "BSD-2-Clause", - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/uri-js/node_modules/punycode": { - "version": "2.1.1", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/url": { - "version": "0.11.0", - "dev": true, - "license": "MIT", - "dependencies": { - "punycode": "1.3.2", - "querystring": "0.2.0" - } - }, - "node_modules/url/node_modules/punycode": { - "version": "1.3.2", - "dev": true, - "license": "MIT" - }, - "node_modules/ursa-optional": { - "version": "0.10.2", - "hasInstallScript": true, - "license": "Apache-2.0", - "dependencies": { - "bindings": "^1.5.0", - "nan": "^2.14.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/user-home": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "os-homedir": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/utf8-byte-length": { - "version": "1.0.4", - "license": "WTFPL" - }, - "node_modules/util": { - "version": "0.12.5", - "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "is-arguments": "^1.0.4", - "is-generator-function": "^1.0.7", - "is-typed-array": "^1.1.3", - "which-typed-array": "^1.1.2" - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "license": "MIT" - }, - "node_modules/util-extend": { - "version": "1.0.3", - "dev": true, - "license": "MIT" - }, - "node_modules/utils-merge": { - "version": "1.0.1", - "license": "MIT", - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/uuid": { - "version": "8.3.2", - "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/v8-compile-cache": { - "version": "2.3.0", - "dev": true, - "license": "MIT" - }, - "node_modules/v8-compile-cache-lib": { - "version": "3.0.1", - "dev": true, - "license": "MIT" - }, - "node_modules/v8-to-istanbul": { - "version": "9.0.1", - "dev": true, - "license": "ISC", - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.12", - "@types/istanbul-lib-coverage": "^2.0.1", - "convert-source-map": "^1.6.0" - }, - "engines": { - "node": ">=10.12.0" - } - }, - "node_modules/v8-to-istanbul/node_modules/convert-source-map": { - "version": "1.9.0", - "dev": true, - "license": "MIT" - }, - "node_modules/varint": { - "version": "6.0.0", - "license": "MIT" - }, - "node_modules/vary": { - "version": "1.1.2", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/verror": { - "version": "1.10.0", - "engines": [ - "node >=0.6.0" - ], - "license": "MIT", - "dependencies": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } - }, - "node_modules/verror/node_modules/core-util-is": { - "version": "1.0.2", - "license": "MIT" - }, - "node_modules/vm-browserify": { - "version": "1.1.2", - "dev": true, - "license": "MIT" - }, - "node_modules/void-elements": { - "version": "2.0.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/vscode-oniguruma": { - "version": "1.6.2", - "dev": true, - "license": "MIT" - }, - "node_modules/vscode-textmate": { - "version": "5.2.0", - "dev": true, - "license": "MIT" - }, - "node_modules/watchpack": { - "version": "2.4.0", - "dev": true, - "license": "MIT", - "dependencies": { - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.1.2" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/wcwidth": { - "version": "1.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "defaults": "^1.0.3" - } - }, - "node_modules/weak-lru-cache": { - "version": "1.2.2", - "dev": true, - "license": "MIT" - }, - "node_modules/web-encoding": { - "version": "1.1.5", - "license": "MIT", - "dependencies": { - "util": "^0.12.3" - }, - "optionalDependencies": { - "@zxing/text-encoding": "0.9.0" - } - }, - "node_modules/webidl-conversions": { - "version": "3.0.1", - "license": "BSD-2-Clause" - }, - "node_modules/webpack": { - "version": "5.74.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/eslint-scope": "^3.7.3", - "@types/estree": "^0.0.51", - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/wasm-edit": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1", - "acorn": "^8.7.1", - "acorn-import-assertions": "^1.7.6", - "browserslist": "^4.14.5", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.10.0", - "es-module-lexer": "^0.9.0", - "eslint-scope": "5.1.1", - "events": "^3.2.0", - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.9", - "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.2.0", - "mime-types": "^2.1.27", - "neo-async": "^2.6.2", - "schema-utils": "^3.1.0", - "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.1.3", - "watchpack": "^2.4.0", - "webpack-sources": "^3.2.3" - }, - "bin": { - "webpack": "bin/webpack.js" - }, - "engines": { - "node": ">=10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependenciesMeta": { - "webpack-cli": { - "optional": true - } - } - }, - "node_modules/webpack-cli": { - "version": "4.10.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@discoveryjs/json-ext": "^0.5.0", - "@webpack-cli/configtest": "^1.2.0", - "@webpack-cli/info": "^1.5.0", - "@webpack-cli/serve": "^1.7.0", - "colorette": "^2.0.14", - "commander": "^7.0.0", - "cross-spawn": "^7.0.3", - "fastest-levenshtein": "^1.0.12", - "import-local": "^3.0.2", - "interpret": "^2.2.0", - "rechoir": "^0.7.0", - "webpack-merge": "^5.7.3" - }, - "bin": { - "webpack-cli": "bin/cli.js" - }, - "engines": { - "node": ">=10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "4.x.x || 5.x.x" - }, - "peerDependenciesMeta": { - "@webpack-cli/generators": { - "optional": true - }, - "@webpack-cli/migrate": { - "optional": true - }, - "webpack-bundle-analyzer": { - "optional": true - }, - "webpack-dev-server": { - "optional": true - } - } - }, - "node_modules/webpack-cli/node_modules/commander": { - "version": "7.2.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 10" - } - }, - "node_modules/webpack-merge": { - "version": "5.8.0", - "dev": true, - "license": "MIT", - "dependencies": { - "clone-deep": "^4.0.1", - "wildcard": "^2.0.0" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/webpack-sources": { - "version": "3.2.3", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/webpack/node_modules/events": { - "version": "3.3.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.x" - } - }, - "node_modules/webpack/node_modules/schema-utils": { - "version": "3.1.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/whatwg-url": { - "version": "5.0.0", - "license": "MIT", - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "node_modules/which": { - "version": "1.3.1", - "dev": true, - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/which-boxed-primitive": { - "version": "1.0.2", - "license": "MIT", - "dependencies": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-collection": { - "version": "1.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "is-map": "^2.0.1", - "is-set": "^2.0.1", - "is-weakmap": "^2.0.1", - "is-weakset": "^2.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-module": { - "version": "2.0.0", - "dev": true, - "license": "ISC" - }, - "node_modules/which-typed-array": { - "version": "1.1.8", - "license": "MIT", - "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "es-abstract": "^1.20.0", - "for-each": "^0.3.3", - "has-tostringtag": "^1.0.0", - "is-typed-array": "^1.1.9" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/wildcard": { - "version": "2.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/winston": { - "version": "3.8.2", - "license": "MIT", - "dependencies": { - "@colors/colors": "1.5.0", - "@dabh/diagnostics": "^2.0.2", - "async": "^3.2.3", - "is-stream": "^2.0.0", - "logform": "^2.4.0", - "one-time": "^1.0.0", - "readable-stream": "^3.4.0", - "safe-stable-stringify": "^2.3.1", - "stack-trace": "0.0.x", - "triple-beam": "^1.3.0", - "winston-transport": "^4.5.0" - }, - "engines": { - "node": ">= 12.0.0" - } - }, - "node_modules/winston-daily-rotate-file": { - "version": "4.7.1", - "license": "MIT", - "dependencies": { - "file-stream-rotator": "^0.6.1", - "object-hash": "^2.0.1", - "triple-beam": "^1.3.0", - "winston-transport": "^4.4.0" - }, - "engines": { - "node": ">=8" - }, - "peerDependencies": { - "winston": "^3" - } - }, - "node_modules/winston-transport": { - "version": "4.5.0", - "license": "MIT", - "dependencies": { - "logform": "^2.3.2", - "readable-stream": "^3.6.0", - "triple-beam": "^1.3.0" - }, - "engines": { - "node": ">= 6.4.0" - } - }, - "node_modules/winston-transport/node_modules/readable-stream": { - "version": "3.6.0", - "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/winston/node_modules/readable-stream": { - "version": "3.6.0", - "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/word-wrap": { - "version": "1.2.3", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/wordwrap": { - "version": "1.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/wrap-ansi": { - "version": "7.0.0", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/emoji-regex": { - "version": "8.0.0", - "license": "MIT" - }, - "node_modules/wrap-ansi/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi/node_modules/string-width": { - "version": "4.2.3", - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "dev": true, - "license": "ISC" - }, - "node_modules/write": { - "version": "0.2.1", - "dev": true, - "license": "MIT", - "dependencies": { - "mkdirp": "^0.5.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/write-file-atomic": { - "version": "3.0.3", - "dev": true, - "license": "ISC", - "dependencies": { - "imurmurhash": "^0.1.4", - "is-typedarray": "^1.0.0", - "signal-exit": "^3.0.2", - "typedarray-to-buffer": "^3.1.5" - } - }, - "node_modules/ws": { - "version": "7.5.9", - "license": "MIT", - "engines": { - "node": ">=8.3.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/xml2js": { - "version": "0.4.23", - "license": "MIT", - "dependencies": { - "sax": ">=0.6.0", - "xmlbuilder": "~11.0.0" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/xmlbuilder": { - "version": "11.0.1", - "license": "MIT", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/xor-distance": { - "version": "2.0.0", - "license": "MIT" - }, - "node_modules/xsalsa20": { - "version": "1.2.0", - "license": "MIT" - }, - "node_modules/xtend": { - "version": "4.0.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.4" - } - }, - "node_modules/y18n": { - "version": "5.0.8", - "license": "ISC", - "engines": { - "node": ">=10" - } - }, - "node_modules/yaml": { - "version": "2.1.3", - "dev": true, - "license": "ISC", - "engines": { - "node": ">= 14" - } - }, - "node_modules/yargs": { - "version": "16.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs-parser": { - "version": "20.2.9", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs/node_modules/emoji-regex": { - "version": "8.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/yargs/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/yargs/node_modules/string-width": { - "version": "4.2.3", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/yn": { - "version": "3.1.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "packages/block": { - "name": "@ethereumjs/block", - "version": "4.2.1", - "license": "MPL-2.0", - "dependencies": { - "@ethereumjs/common": "^3.1.1", - "@ethereumjs/rlp": "^4.0.1", - "@ethereumjs/trie": "^5.0.4", - "@ethereumjs/tx": "^4.1.1", - "@ethereumjs/util": "^8.0.5", - "ethereum-cryptography": "^2.0.0" - }, - "devDependencies": { - "c-kzg": "^2.0.4", - "testdouble": "^3.17.2" - }, - "engines": { - "node": ">=16" - } - }, - "packages/blockchain": { - "name": "@ethereumjs/blockchain", - "version": "6.2.1", - "license": "MPL-2.0", - "dependencies": { - "@ethereumjs/block": "^4.2.1", - "@ethereumjs/common": "^3.1.1", - "@ethereumjs/ethash": "^2.0.4", - "@ethereumjs/rlp": "^4.0.1", - "@ethereumjs/trie": "^5.0.4", - "@ethereumjs/tx": "^4.1.1", - "@ethereumjs/util": "^8.0.5", - "debug": "^4.3.3", - "ethereum-cryptography": "^2.0.0", - "level": "^8.0.0", - "lru-cache": "^7.18.3" - }, - "devDependencies": { - "@types/async": "^2.4.1", - "@types/level-errors": "^3.0.0" - }, - "engines": { - "node": ">=16" - } - }, - "packages/client": { - "name": "@ethereumjs/client", - "version": "0.7.0", - "hasInstallScript": true, - "license": "MPL-2.0", - "dependencies": { - "@chainsafe/libp2p-noise": "^4.1.1", - "@ethereumjs/block": "4.2.1", - "@ethereumjs/blockchain": "6.2.1", - "@ethereumjs/common": "3.1.1", - "@ethereumjs/devp2p": "5.1.1", - "@ethereumjs/ethash": "2.0.4", - "@ethereumjs/evm": "1.3.1", - "@ethereumjs/rlp": "4.0.1", - "@ethereumjs/statemanager": "1.0.4", - "@ethereumjs/trie": "5.0.4", - "@ethereumjs/tx": "4.1.1", - "@ethereumjs/util": "8.0.5", - "@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", - "debug": "^4.3.3", - "ethereum-cryptography": "^2.0.0", - "fs-extra": "^10.1.0", - "it-pipe": "^1.1.0", - "jayson": "^4.0.0", - "jwt-simple": "^0.5.6", - "level": "^8.0.0", - "libp2p": "^0.30.7", - "libp2p-bootstrap": "^0.14.0", - "libp2p-interfaces": "^1.2.0", - "libp2p-kad-dht": "^0.20.6", - "libp2p-mplex": "^0.10.2", - "libp2p-tcp": "^0.15.3", - "libp2p-websockets": "^0.15.1", - "memory-level": "^1.0.0", - "multiaddr": "^10.0.1", - "peer-id": "^0.14.3", - "qheap": "^1.4.0", - "winston": "^3.3.3", - "winston-daily-rotate-file": "^4.5.5", - "yargs": "^17.7.1" - }, - "bin": { - "ethereumjs": "dist/bin/cli.js" - }, - "devDependencies": { - "@types/body-parser": "^1.19.2", - "@types/connect": "^3.4.35", - "@types/fs-extra": "^9.0.13", - "@types/jwt-simple": "^0.5.33", - "@types/yargs": "^17.0.24", - "constants-browserify": "^1.0.0", - "crypto-browserify": "^3.12.0", - "file-replace-loader": "^1.2.0", - "it-pair": "^1.0.0", - "it-pushable": "^1.4.2", - "os-browserify": "^0.3.0", - "pino": "^5.8.0", - "process": "^0.11.10", - "stream-browserify": "^3.0.0", - "supertest": "^6.1.3", - "superwstest": "^2.0.1", - "testdouble": "^3.16.6", - "testdouble-timers": "^0.1.1", - "util": "^0.12.4", - "webpack": "^5.55.1", - "webpack-cli": "^4.8.0" - }, - "engines": { - "node": ">=16" - } - }, - "packages/client/node_modules/cliui": { - "version": "8.0.1", - "license": "ISC", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "packages/client/node_modules/emoji-regex": { - "version": "8.0.0", - "license": "MIT" - }, - "packages/client/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "packages/client/node_modules/string-width": { - "version": "4.2.3", - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "packages/client/node_modules/yargs": { - "version": "17.7.1", - "license": "MIT", - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "packages/client/node_modules/yargs-parser": { - "version": "21.1.1", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "packages/common": { - "name": "@ethereumjs/common", - "version": "3.1.1", - "license": "MIT", - "dependencies": { - "@ethereumjs/util": "^8.0.5", - "crc-32": "^1.2.0" - } - }, - "packages/devp2p": { - "name": "@ethereumjs/devp2p", - "version": "5.1.1", - "license": "MIT", - "dependencies": { - "@ethereumjs/common": "^3.1.1", - "@ethereumjs/rlp": "^4.0.1", - "@ethereumjs/util": "^8.0.5", - "@scure/base": "1.1.1", - "@types/k-bucket": "^5.0.0", - "debug": "^4.3.3", - "ethereum-cryptography": "^2.0.0", - "k-bucket": "^5.0.0", - "lru-cache": "^7.18.3", - "ms": "^0.7.1", - "multiaddr": "^10.0.1", - "scanf": "^1.1.2", - "snappyjs": "^0.6.1" - }, - "devDependencies": { - "@ethereumjs/block": "^4.2.1", - "@ethereumjs/tx": "^4.1.1", - "@types/chalk": "^2.2.0", - "@types/debug": "^4.1.4", - "@types/ip": "^1.1.0", - "@types/ms": "^0.7.30", - "chalk": "^2.4.2", - "testdouble": "^3.8.2" - }, - "engines": { - "node": ">=16" - } - }, - "packages/devp2p/node_modules/ansi-styles": { - "version": "3.2.1", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "packages/devp2p/node_modules/chalk": { - "version": "2.4.2", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "packages/devp2p/node_modules/color-convert": { - "version": "1.9.3", - "dev": true, - "license": "MIT", - "dependencies": { - "color-name": "1.1.3" - } - }, - "packages/devp2p/node_modules/color-name": { - "version": "1.1.3", - "dev": true, - "license": "MIT" - }, - "packages/devp2p/node_modules/has-flag": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "packages/devp2p/node_modules/supports-color": { - "version": "5.5.0", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "packages/ethash": { - "name": "@ethereumjs/ethash", - "version": "2.0.4", - "license": "MPL-2.0", - "dependencies": { - "@ethereumjs/block": "^4.2.1", - "@ethereumjs/rlp": "^4.0.1", - "@ethereumjs/util": "^8.0.5", - "bigint-crypto-utils": "^3.0.23", - "ethereum-cryptography": "^2.0.0" - }, - "devDependencies": { - "@ethereumjs/common": "^3.1.1" - }, - "engines": { - "node": ">=16" - } - }, - "packages/evm": { - "name": "@ethereumjs/evm", - "version": "1.3.1", - "license": "MPL-2.0", - "dependencies": { - "@ethereumjs/common": "^3.1.1", - "@ethereumjs/statemanager": "^1.0.4", - "@ethereumjs/util": "^8.0.5", - "debug": "^4.3.3", - "ethereum-cryptography": "^2.0.0", - "mcl-wasm": "^0.7.1", - "rustbn.js": "~0.2.0" - }, - "devDependencies": { - "@ethereumjs/statemanager": "^1.0.4", - "@ethersproject/abi": "^5.0.12", - "@types/benchmark": "^1.0.33", - "@types/core-js": "^2.5.0", - "@types/minimist": "^1.2.2", - "@types/node-dir": "^0.0.34", - "benchmark": "^2.1.4", - "c-kzg": "^2.0.4", - "level": "^8.0.0", - "memory-level": "^1.0.0", - "minimist": "^1.2.5", - "node-dir": "^0.1.17", - "solc": "^0.8.1" - }, - "engines": { - "node": ">=16" - } - }, - "packages/rlp": { - "name": "@ethereumjs/rlp", - "version": "4.0.1", - "license": "MPL-2.0", - "bin": { - "rlp": "bin/rlp" - }, - "engines": { - "node": ">=16" - } - }, - "packages/statemanager": { - "name": "@ethereumjs/statemanager", - "version": "1.0.4", - "license": "MPL-2.0", - "dependencies": { - "@ethereumjs/common": "^3.1.1", - "@ethereumjs/rlp": "^4.0.1", - "debug": "^4.3.3", - "ethereum-cryptography": "^2.0.0", - "ethers": "^5.7.1", - "js-sdsl": "^4.1.4", - "lru-cache": "^7.18.3" - }, - "devDependencies": { - "@ethereumjs/block": "^4.2.1", - "@ethereumjs/trie": "^5.0.4", - "@ethereumjs/util": "^8.0.5", - "@types/node": "^16.11.7", - "@types/tape": "^4.13.2", - "debug": "^4.3.3", - "eslint": "^8.0.0", - "ethereum-cryptography": "^2.0.0", - "functional-red-black-tree": "^1.0.1", - "karma": "^6.3.2", - "karma-chrome-launcher": "^3.1.0", - "karma-firefox-launcher": "^2.1.0", - "karma-tap": "^4.2.0", - "karma-typescript": "^5.5.3", - "nyc": "^15.1.0", - "standard": "^10.0.0", - "tape": "^5.3.1", - "ts-node": "^10.2.1", - "typescript": "^4.4.2" - } - }, - "packages/trie": { - "name": "@ethereumjs/trie", - "version": "5.0.4", - "license": "MPL-2.0", - "dependencies": { - "@ethereumjs/rlp": "^4.0.1", - "@ethereumjs/util": "^8.0.5", - "@types/readable-stream": "^2.3.13", - "ethereum-cryptography": "^2.0.0", - "lru-cache": "^7.18.3", - "readable-stream": "^3.6.0" - }, - "devDependencies": { - "@types/benchmark": "^1.0.33", - "0x": "^4.9.1", - "abstract-level": "^1.0.3", - "level": "^8.0.0", - "level-legacy": "npm:level@^7.0.0", - "level-mem": "^6.0.1", - "levelup": "^5.1.1", - "lmdb": "^2.5.3", - "memory-level": "^1.0.0", - "micro-bmark": "0.2.0" - }, - "engines": { - "node": ">=16" - } - }, - "packages/trie/node_modules/readable-stream": { - "version": "3.6.0", - "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "packages/tx": { - "name": "@ethereumjs/tx", - "version": "4.1.1", - "license": "MPL-2.0", - "dependencies": { - "@chainsafe/ssz": "^0.11.0", - "@ethereumjs/common": "^3.1.1", - "@ethereumjs/rlp": "^4.0.1", - "@ethereumjs/util": "^8.0.5", - "ethereum-cryptography": "^2.0.0" - }, - "devDependencies": { - "@types/minimist": "^1.2.0", - "@types/node-dir": "^0.0.34", - "minimist": "^1.2.0", - "node-dir": "^0.1.16", - "testdouble": "^3.17.2" - }, - "engines": { - "node": ">=16" - }, - "peerDependencies": { - "c-kzg": "^2.0.4" - }, - "peerDependenciesMeta": { - "c-kzg": { - "optional": true - } - } - }, - "packages/util": { - "name": "@ethereumjs/util", - "version": "8.0.5", - "license": "MPL-2.0", - "dependencies": { - "@chainsafe/ssz": "^0.11.0", - "@ethereumjs/rlp": "^4.0.1", - "ethereum-cryptography": "^2.0.0" - }, - "devDependencies": { - "@types/bn.js": "^5.1.0", - "@types/secp256k1": "^4.0.1" - }, - "engines": { - "node": ">=16" - }, - "peerDependencies": { - "c-kzg": "^2.0.4" - }, - "peerDependenciesMeta": { - "c-kzg": { - "optional": true - } - } - }, - "packages/vm": { - "name": "@ethereumjs/vm", - "version": "6.4.1", - "license": "MPL-2.0", - "dependencies": { - "@ethereumjs/block": "^4.2.1", - "@ethereumjs/blockchain": "^6.2.1", - "@ethereumjs/common": "^3.1.1", - "@ethereumjs/evm": "^1.3.1", - "@ethereumjs/rlp": "^4.0.1", - "@ethereumjs/statemanager": "^1.0.4", - "@ethereumjs/trie": "^5.0.4", - "@ethereumjs/tx": "^4.1.1", - "@ethereumjs/util": "^8.0.5", - "debug": "^4.3.3", - "ethereum-cryptography": "^2.0.0", - "mcl-wasm": "^0.7.1", - "rustbn.js": "~0.2.0" - }, - "devDependencies": { - "@ethersproject/abi": "^5.0.12", - "@types/benchmark": "^1.0.33", - "@types/core-js": "^2.5.0", - "@types/minimist": "^1.2.2", - "@types/node-dir": "^0.0.34", - "benchmark": "^2.1.4", - "c-kzg": "^2.0.4", - "minimist": "^1.2.5", - "node-dir": "^0.1.17", - "nyc": "^15.1.0", - "prettier": "^2.0.5", - "solc": "^0.8.1", - "standard": "^10.0.0", - "tape": "^5.3.1", - "ts-node": "^10.2.1", - "typedoc": "^0.22.4", - "typescript": "^4.4.2" - }, - "engines": { - "node": ">=16" - } - }, - "packages/vm/node_modules/brace-expansion": { - "version": "2.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "packages/vm/node_modules/glob": { - "version": "8.0.3", - "dev": true, - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "packages/vm/node_modules/minimatch": { - "version": "5.1.0", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "packages/vm/node_modules/typedoc": { - "version": "0.22.18", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "glob": "^8.0.3", - "lunr": "^2.3.9", - "marked": "^4.0.16", - "minimatch": "^5.1.0", - "shiki": "^0.10.1" - }, - "bin": { - "typedoc": "bin/typedoc" - }, - "engines": { - "node": ">= 12.10.0" - }, - "peerDependencies": { - "typescript": "4.0.x || 4.1.x || 4.2.x || 4.3.x || 4.4.x || 4.5.x || 4.6.x || 4.7.x" - } - } - }, - "dependencies": { - "@ampproject/remapping": { - "version": "2.2.0", - "dev": true, - "requires": { - "@jridgewell/gen-mapping": "^0.1.0", - "@jridgewell/trace-mapping": "^0.3.9" - } - }, - "@babel/code-frame": { - "version": "7.12.11", - "dev": true, - "requires": { - "@babel/highlight": "^7.10.4" - } - }, - "@babel/compat-data": { - "version": "7.19.4", - "dev": true - }, - "@babel/core": { - "version": "7.19.6", - "dev": true, - "requires": { - "@ampproject/remapping": "^2.1.0", - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.19.6", - "@babel/helper-compilation-targets": "^7.19.3", - "@babel/helper-module-transforms": "^7.19.6", - "@babel/helpers": "^7.19.4", - "@babel/parser": "^7.19.6", - "@babel/template": "^7.18.10", - "@babel/traverse": "^7.19.6", - "@babel/types": "^7.19.4", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.1", - "semver": "^6.3.0" - }, - "dependencies": { - "@babel/code-frame": { - "version": "7.18.6", - "dev": true, - "requires": { - "@babel/highlight": "^7.18.6" - } - }, - "convert-source-map": { - "version": "1.9.0", - "dev": true - }, - "semver": { - "version": "6.3.0", - "dev": true - } - } - }, - "@babel/generator": { - "version": "7.19.6", - "dev": true, - "requires": { - "@babel/types": "^7.19.4", - "@jridgewell/gen-mapping": "^0.3.2", - "jsesc": "^2.5.1" - }, - "dependencies": { - "@jridgewell/gen-mapping": { - "version": "0.3.2", - "dev": true, - "requires": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - } - } - } - }, - "@babel/helper-annotate-as-pure": { - "version": "7.18.6", - "dev": true, - "requires": { - "@babel/types": "^7.18.6" - } - }, - "@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.18.9", - "dev": true, - "requires": { - "@babel/helper-explode-assignable-expression": "^7.18.6", - "@babel/types": "^7.18.9" - } - }, - "@babel/helper-compilation-targets": { - "version": "7.19.3", - "dev": true, - "requires": { - "@babel/compat-data": "^7.19.3", - "@babel/helper-validator-option": "^7.18.6", - "browserslist": "^4.21.3", - "semver": "^6.3.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "dev": true - } - } - }, - "@babel/helper-create-class-features-plugin": { - "version": "7.19.0", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-function-name": "^7.19.0", - "@babel/helper-member-expression-to-functions": "^7.18.9", - "@babel/helper-optimise-call-expression": "^7.18.6", - "@babel/helper-replace-supers": "^7.18.9", - "@babel/helper-split-export-declaration": "^7.18.6" - } - }, - "@babel/helper-create-regexp-features-plugin": { - "version": "7.19.0", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "regexpu-core": "^5.1.0" - } - }, - "@babel/helper-define-polyfill-provider": { - "version": "0.3.3", - "dev": true, - "requires": { - "@babel/helper-compilation-targets": "^7.17.7", - "@babel/helper-plugin-utils": "^7.16.7", - "debug": "^4.1.1", - "lodash.debounce": "^4.0.8", - "resolve": "^1.14.2", - "semver": "^6.1.2" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "dev": true - } - } - }, - "@babel/helper-environment-visitor": { - "version": "7.18.9", - "dev": true - }, - "@babel/helper-explode-assignable-expression": { - "version": "7.18.6", - "dev": true, - "requires": { - "@babel/types": "^7.18.6" - } - }, - "@babel/helper-function-name": { - "version": "7.19.0", - "dev": true, - "requires": { - "@babel/template": "^7.18.10", - "@babel/types": "^7.19.0" - } - }, - "@babel/helper-hoist-variables": { - "version": "7.18.6", - "dev": true, - "requires": { - "@babel/types": "^7.18.6" - } - }, - "@babel/helper-member-expression-to-functions": { - "version": "7.18.9", - "dev": true, - "requires": { - "@babel/types": "^7.18.9" - } - }, - "@babel/helper-module-imports": { - "version": "7.18.6", - "dev": true, - "requires": { - "@babel/types": "^7.18.6" - } - }, - "@babel/helper-module-transforms": { - "version": "7.19.6", - "dev": true, - "requires": { - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-simple-access": "^7.19.4", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/helper-validator-identifier": "^7.19.1", - "@babel/template": "^7.18.10", - "@babel/traverse": "^7.19.6", - "@babel/types": "^7.19.4" - } - }, - "@babel/helper-optimise-call-expression": { - "version": "7.18.6", - "dev": true, - "requires": { - "@babel/types": "^7.18.6" - } - }, - "@babel/helper-plugin-utils": { - "version": "7.19.0", - "dev": true - }, - "@babel/helper-remap-async-to-generator": { - "version": "7.18.9", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-wrap-function": "^7.18.9", - "@babel/types": "^7.18.9" - } - }, - "@babel/helper-replace-supers": { - "version": "7.19.1", - "dev": true, - "requires": { - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-member-expression-to-functions": "^7.18.9", - "@babel/helper-optimise-call-expression": "^7.18.6", - "@babel/traverse": "^7.19.1", - "@babel/types": "^7.19.0" - } - }, - "@babel/helper-simple-access": { - "version": "7.19.4", - "dev": true, - "requires": { - "@babel/types": "^7.19.4" - } - }, - "@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.18.9", - "dev": true, - "requires": { - "@babel/types": "^7.18.9" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.18.6", - "dev": true, - "requires": { - "@babel/types": "^7.18.6" - } - }, - "@babel/helper-string-parser": { - "version": "7.19.4", - "dev": true - }, - "@babel/helper-validator-identifier": { - "version": "7.19.1", - "dev": true - }, - "@babel/helper-validator-option": { - "version": "7.18.6", - "dev": true - }, - "@babel/helper-wrap-function": { - "version": "7.19.0", - "dev": true, - "requires": { - "@babel/helper-function-name": "^7.19.0", - "@babel/template": "^7.18.10", - "@babel/traverse": "^7.19.0", - "@babel/types": "^7.19.0" - } - }, - "@babel/helpers": { - "version": "7.19.4", - "dev": true, - "requires": { - "@babel/template": "^7.18.10", - "@babel/traverse": "^7.19.4", - "@babel/types": "^7.19.4" - } - }, - "@babel/highlight": { - "version": "7.18.6", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.18.6", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "color-convert": { - "version": "1.9.3", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "dev": true - }, - "has-flag": { - "version": "3.0.0", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "@babel/parser": { - "version": "7.19.6", - "dev": true - }, - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { - "version": "7.18.6", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { - "version": "7.18.9", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.9", - "@babel/helper-skip-transparent-expression-wrappers": "^7.18.9", - "@babel/plugin-proposal-optional-chaining": "^7.18.9" - } - }, - "@babel/plugin-proposal-async-generator-functions": { - "version": "7.19.1", - "dev": true, - "requires": { - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-plugin-utils": "^7.19.0", - "@babel/helper-remap-async-to-generator": "^7.18.9", - "@babel/plugin-syntax-async-generators": "^7.8.4" - } - }, - "@babel/plugin-proposal-class-properties": { - "version": "7.18.6", - "dev": true, - "requires": { - "@babel/helper-create-class-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-proposal-class-static-block": { - "version": "7.18.6", - "dev": true, - "requires": { - "@babel/helper-create-class-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-class-static-block": "^7.14.5" - } - }, - "@babel/plugin-proposal-dynamic-import": { - "version": "7.18.6", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-dynamic-import": "^7.8.3" - } - }, - "@babel/plugin-proposal-export-namespace-from": { - "version": "7.18.9", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.9", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3" - } - }, - "@babel/plugin-proposal-json-strings": { - "version": "7.18.6", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-json-strings": "^7.8.3" - } - }, - "@babel/plugin-proposal-logical-assignment-operators": { - "version": "7.18.9", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.9", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" - } - }, - "@babel/plugin-proposal-nullish-coalescing-operator": { - "version": "7.18.6", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" - } - }, - "@babel/plugin-proposal-numeric-separator": { - "version": "7.18.6", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-numeric-separator": "^7.10.4" - } - }, - "@babel/plugin-proposal-object-rest-spread": { - "version": "7.19.4", - "dev": true, - "requires": { - "@babel/compat-data": "^7.19.4", - "@babel/helper-compilation-targets": "^7.19.3", - "@babel/helper-plugin-utils": "^7.19.0", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-transform-parameters": "^7.18.8" - } - }, - "@babel/plugin-proposal-optional-catch-binding": { - "version": "7.18.6", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" - } - }, - "@babel/plugin-proposal-optional-chaining": { - "version": "7.18.9", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.9", - "@babel/helper-skip-transparent-expression-wrappers": "^7.18.9", - "@babel/plugin-syntax-optional-chaining": "^7.8.3" - } - }, - "@babel/plugin-proposal-private-methods": { - "version": "7.18.6", - "dev": true, - "requires": { - "@babel/helper-create-class-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-proposal-private-property-in-object": { - "version": "7.18.6", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-create-class-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5" - } - }, - "@babel/plugin-proposal-unicode-property-regex": { - "version": "7.18.6", - "dev": true, - "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-syntax-async-generators": { - "version": "7.8.4", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-class-properties": { - "version": "7.12.13", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.12.13" - } - }, - "@babel/plugin-syntax-class-static-block": { - "version": "7.14.5", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-syntax-dynamic-import": { - "version": "7.8.3", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-export-namespace-from": { - "version": "7.8.3", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.3" - } - }, - "@babel/plugin-syntax-import-assertions": { - "version": "7.18.6", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-syntax-json-strings": { - "version": "7.8.3", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-logical-assignment-operators": { - "version": "7.10.4", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-syntax-nullish-coalescing-operator": { - "version": "7.8.3", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-numeric-separator": { - "version": "7.10.4", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-syntax-object-rest-spread": { - "version": "7.8.3", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-optional-catch-binding": { - "version": "7.8.3", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-optional-chaining": { - "version": "7.8.3", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-private-property-in-object": { - "version": "7.14.5", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-syntax-top-level-await": { - "version": "7.14.5", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-transform-arrow-functions": { - "version": "7.18.6", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-transform-async-to-generator": { - "version": "7.18.6", - "dev": true, - "requires": { - "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/helper-remap-async-to-generator": "^7.18.6" - } - }, - "@babel/plugin-transform-block-scoped-functions": { - "version": "7.18.6", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-transform-block-scoping": { - "version": "7.19.4", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.19.0" - } - }, - "@babel/plugin-transform-classes": { - "version": "7.19.0", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-compilation-targets": "^7.19.0", - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-function-name": "^7.19.0", - "@babel/helper-optimise-call-expression": "^7.18.6", - "@babel/helper-plugin-utils": "^7.19.0", - "@babel/helper-replace-supers": "^7.18.9", - "@babel/helper-split-export-declaration": "^7.18.6", - "globals": "^11.1.0" - }, - "dependencies": { - "globals": { - "version": "11.12.0", - "dev": true - } - } - }, - "@babel/plugin-transform-computed-properties": { - "version": "7.18.9", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.9" - } - }, - "@babel/plugin-transform-destructuring": { - "version": "7.19.4", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.19.0" - } - }, - "@babel/plugin-transform-dotall-regex": { - "version": "7.18.6", - "dev": true, - "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-transform-duplicate-keys": { - "version": "7.18.9", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.9" - } - }, - "@babel/plugin-transform-exponentiation-operator": { - "version": "7.18.6", - "dev": true, - "requires": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-transform-for-of": { - "version": "7.18.8", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-transform-function-name": { - "version": "7.18.9", - "dev": true, - "requires": { - "@babel/helper-compilation-targets": "^7.18.9", - "@babel/helper-function-name": "^7.18.9", - "@babel/helper-plugin-utils": "^7.18.9" - } - }, - "@babel/plugin-transform-literals": { - "version": "7.18.9", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.9" - } - }, - "@babel/plugin-transform-member-expression-literals": { - "version": "7.18.6", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-transform-modules-amd": { - "version": "7.19.6", - "dev": true, - "requires": { - "@babel/helper-module-transforms": "^7.19.6", - "@babel/helper-plugin-utils": "^7.19.0" - } - }, - "@babel/plugin-transform-modules-commonjs": { - "version": "7.19.6", - "dev": true, - "requires": { - "@babel/helper-module-transforms": "^7.19.6", - "@babel/helper-plugin-utils": "^7.19.0", - "@babel/helper-simple-access": "^7.19.4" - } - }, - "@babel/plugin-transform-modules-systemjs": { - "version": "7.19.6", - "dev": true, - "requires": { - "@babel/helper-hoist-variables": "^7.18.6", - "@babel/helper-module-transforms": "^7.19.6", - "@babel/helper-plugin-utils": "^7.19.0", - "@babel/helper-validator-identifier": "^7.19.1" - } - }, - "@babel/plugin-transform-modules-umd": { - "version": "7.18.6", - "dev": true, - "requires": { - "@babel/helper-module-transforms": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.19.1", - "dev": true, - "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.19.0", - "@babel/helper-plugin-utils": "^7.19.0" - } - }, - "@babel/plugin-transform-new-target": { - "version": "7.18.6", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-transform-object-super": { - "version": "7.18.6", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/helper-replace-supers": "^7.18.6" - } - }, - "@babel/plugin-transform-parameters": { - "version": "7.18.8", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-transform-property-literals": { - "version": "7.18.6", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-transform-regenerator": { - "version": "7.18.6", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6", - "regenerator-transform": "^0.15.0" - } - }, - "@babel/plugin-transform-reserved-words": { - "version": "7.18.6", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-transform-shorthand-properties": { - "version": "7.18.6", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-transform-spread": { - "version": "7.19.0", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.19.0", - "@babel/helper-skip-transparent-expression-wrappers": "^7.18.9" - } - }, - "@babel/plugin-transform-sticky-regex": { - "version": "7.18.6", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-transform-template-literals": { - "version": "7.18.9", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.9" - } - }, - "@babel/plugin-transform-typeof-symbol": { - "version": "7.18.9", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.9" - } - }, - "@babel/plugin-transform-unicode-escapes": { - "version": "7.18.10", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.9" - } - }, - "@babel/plugin-transform-unicode-regex": { - "version": "7.18.6", - "dev": true, - "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/preset-env": { - "version": "7.19.4", - "dev": true, - "requires": { - "@babel/compat-data": "^7.19.4", - "@babel/helper-compilation-targets": "^7.19.3", - "@babel/helper-plugin-utils": "^7.19.0", - "@babel/helper-validator-option": "^7.18.6", - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.18.6", - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.18.9", - "@babel/plugin-proposal-async-generator-functions": "^7.19.1", - "@babel/plugin-proposal-class-properties": "^7.18.6", - "@babel/plugin-proposal-class-static-block": "^7.18.6", - "@babel/plugin-proposal-dynamic-import": "^7.18.6", - "@babel/plugin-proposal-export-namespace-from": "^7.18.9", - "@babel/plugin-proposal-json-strings": "^7.18.6", - "@babel/plugin-proposal-logical-assignment-operators": "^7.18.9", - "@babel/plugin-proposal-nullish-coalescing-operator": "^7.18.6", - "@babel/plugin-proposal-numeric-separator": "^7.18.6", - "@babel/plugin-proposal-object-rest-spread": "^7.19.4", - "@babel/plugin-proposal-optional-catch-binding": "^7.18.6", - "@babel/plugin-proposal-optional-chaining": "^7.18.9", - "@babel/plugin-proposal-private-methods": "^7.18.6", - "@babel/plugin-proposal-private-property-in-object": "^7.18.6", - "@babel/plugin-proposal-unicode-property-regex": "^7.18.6", - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-class-properties": "^7.12.13", - "@babel/plugin-syntax-class-static-block": "^7.14.5", - "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3", - "@babel/plugin-syntax-import-assertions": "^7.18.6", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.10.4", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5", - "@babel/plugin-syntax-top-level-await": "^7.14.5", - "@babel/plugin-transform-arrow-functions": "^7.18.6", - "@babel/plugin-transform-async-to-generator": "^7.18.6", - "@babel/plugin-transform-block-scoped-functions": "^7.18.6", - "@babel/plugin-transform-block-scoping": "^7.19.4", - "@babel/plugin-transform-classes": "^7.19.0", - "@babel/plugin-transform-computed-properties": "^7.18.9", - "@babel/plugin-transform-destructuring": "^7.19.4", - "@babel/plugin-transform-dotall-regex": "^7.18.6", - "@babel/plugin-transform-duplicate-keys": "^7.18.9", - "@babel/plugin-transform-exponentiation-operator": "^7.18.6", - "@babel/plugin-transform-for-of": "^7.18.8", - "@babel/plugin-transform-function-name": "^7.18.9", - "@babel/plugin-transform-literals": "^7.18.9", - "@babel/plugin-transform-member-expression-literals": "^7.18.6", - "@babel/plugin-transform-modules-amd": "^7.18.6", - "@babel/plugin-transform-modules-commonjs": "^7.18.6", - "@babel/plugin-transform-modules-systemjs": "^7.19.0", - "@babel/plugin-transform-modules-umd": "^7.18.6", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.19.1", - "@babel/plugin-transform-new-target": "^7.18.6", - "@babel/plugin-transform-object-super": "^7.18.6", - "@babel/plugin-transform-parameters": "^7.18.8", - "@babel/plugin-transform-property-literals": "^7.18.6", - "@babel/plugin-transform-regenerator": "^7.18.6", - "@babel/plugin-transform-reserved-words": "^7.18.6", - "@babel/plugin-transform-shorthand-properties": "^7.18.6", - "@babel/plugin-transform-spread": "^7.19.0", - "@babel/plugin-transform-sticky-regex": "^7.18.6", - "@babel/plugin-transform-template-literals": "^7.18.9", - "@babel/plugin-transform-typeof-symbol": "^7.18.9", - "@babel/plugin-transform-unicode-escapes": "^7.18.10", - "@babel/plugin-transform-unicode-regex": "^7.18.6", - "@babel/preset-modules": "^0.1.5", - "@babel/types": "^7.19.4", - "babel-plugin-polyfill-corejs2": "^0.3.3", - "babel-plugin-polyfill-corejs3": "^0.6.0", - "babel-plugin-polyfill-regenerator": "^0.4.1", - "core-js-compat": "^3.25.1", - "semver": "^6.3.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "dev": true - } - } - }, - "@babel/preset-modules": { - "version": "0.1.5", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", - "@babel/plugin-transform-dotall-regex": "^7.4.4", - "@babel/types": "^7.4.4", - "esutils": "^2.0.2" - } - }, - "@babel/runtime": { - "version": "7.19.4", - "dev": true, - "requires": { - "regenerator-runtime": "^0.13.4" - } - }, - "@babel/runtime-corejs3": { - "version": "7.19.6", - "dev": true, - "requires": { - "core-js-pure": "^3.25.1", - "regenerator-runtime": "^0.13.4" - } - }, - "@babel/template": { - "version": "7.18.10", - "dev": true, - "requires": { - "@babel/code-frame": "^7.18.6", - "@babel/parser": "^7.18.10", - "@babel/types": "^7.18.10" - }, - "dependencies": { - "@babel/code-frame": { - "version": "7.18.6", - "dev": true, - "requires": { - "@babel/highlight": "^7.18.6" - } - } - } - }, - "@babel/traverse": { - "version": "7.19.6", - "dev": true, - "requires": { - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.19.6", - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-function-name": "^7.19.0", - "@babel/helper-hoist-variables": "^7.18.6", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/parser": "^7.19.6", - "@babel/types": "^7.19.4", - "debug": "^4.1.0", - "globals": "^11.1.0" - }, - "dependencies": { - "@babel/code-frame": { - "version": "7.18.6", - "dev": true, - "requires": { - "@babel/highlight": "^7.18.6" - } - }, - "globals": { - "version": "11.12.0", - "dev": true - } - } - }, - "@babel/types": { - "version": "7.19.4", - "dev": true, - "requires": { - "@babel/helper-string-parser": "^7.19.4", - "@babel/helper-validator-identifier": "^7.19.1", - "to-fast-properties": "^2.0.0" - } - }, - "@bcoe/v8-coverage": { - "version": "0.2.3", - "dev": true - }, - "@chainsafe/as-sha256": { - "version": "0.4.0" - }, - "@chainsafe/libp2p-noise": { - "version": "4.1.2", - "requires": { - "@stablelib/chacha20poly1305": "^1.0.1", - "@stablelib/hkdf": "^1.0.1", - "@stablelib/sha256": "^1.0.1", - "@stablelib/x25519": "^1.0.1", - "debug": "^4.3.1", - "it-buffer": "^0.1.3", - "it-length-prefixed": "^5.0.3", - "it-pair": "^1.0.0", - "it-pb-rpc": "^0.1.11", - "it-pipe": "^1.1.0", - "libp2p-crypto": "^0.19.7", - "peer-id": "^0.15.3", - "protobufjs": "^6.11.2", - "uint8arrays": "^3.0.0" - }, - "dependencies": { - "err-code": { - "version": "3.0.1" - }, - "peer-id": { - "version": "0.15.4", - "requires": { - "class-is": "^1.1.0", - "libp2p-crypto": "^0.20.0", - "minimist": "^1.2.5", - "multiformats": "^9.4.5", - "protobufjs": "^6.10.2", - "uint8arrays": "^3.0.0" - }, - "dependencies": { - "libp2p-crypto": { - "version": "0.20.0", - "requires": { - "err-code": "^3.0.1", - "iso-random-stream": "^2.0.0", - "keypair": "^1.0.4", - "multiformats": "^9.4.5", - "noble-ed25519": "^1.2.6", - "noble-secp256k1": "^1.2.10", - "node-forge": "^0.10.0", - "pem-jwk": "^2.0.0", - "protobufjs": "^6.11.2", - "uint8arrays": "^3.0.0", - "ursa-optional": "^0.10.1" - } - } - } - } - } - }, - "@chainsafe/persistent-merkle-tree": { - "version": "0.6.0", - "requires": { - "@chainsafe/as-sha256": "^0.4.0", - "@noble/hashes": "^1.3.0" - } - }, - "@chainsafe/ssz": { - "version": "0.11.0", - "requires": { - "@chainsafe/as-sha256": "^0.4.0", - "@chainsafe/persistent-merkle-tree": "^0.6.0" - } - }, - "@colors/colors": { - "version": "1.5.0" - }, - "@cspotcode/source-map-support": { - "version": "0.8.1", - "dev": true, - "requires": { - "@jridgewell/trace-mapping": "0.3.9" - }, - "dependencies": { - "@jridgewell/trace-mapping": { - "version": "0.3.9", - "dev": true, - "requires": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" - } - } - } - }, - "@dabh/diagnostics": { - "version": "2.0.3", - "requires": { - "colorspace": "1.1.x", - "enabled": "2.0.x", - "kuler": "^2.0.0" - } - }, - "@discoveryjs/json-ext": { - "version": "0.5.7", - "dev": true - }, - "@eslint/eslintrc": { - "version": "1.3.3", - "dev": true, - "requires": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.4.0", - "globals": "^13.15.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - } - }, - "@ethereumjs/block": { - "version": "file:packages/block", - "requires": { - "@ethereumjs/common": "^3.1.1", - "@ethereumjs/rlp": "^4.0.1", - "@ethereumjs/trie": "^5.0.4", - "@ethereumjs/tx": "^4.1.1", - "@ethereumjs/util": "^8.0.5", - "c-kzg": "^2.0.4", - "ethereum-cryptography": "^2.0.0", - "testdouble": "^3.17.2" - } - }, - "@ethereumjs/blockchain": { - "version": "file:packages/blockchain", - "requires": { - "@ethereumjs/block": "^4.2.1", - "@ethereumjs/common": "^3.1.1", - "@ethereumjs/ethash": "^2.0.4", - "@ethereumjs/rlp": "^4.0.1", - "@ethereumjs/trie": "^5.0.4", - "@ethereumjs/tx": "^4.1.1", - "@ethereumjs/util": "^8.0.5", - "@types/async": "^2.4.1", - "@types/level-errors": "^3.0.0", - "debug": "^4.3.3", - "ethereum-cryptography": "^2.0.0", - "level": "^8.0.0", - "lru-cache": "^7.18.3" - } - }, - "@ethereumjs/client": { - "version": "file:packages/client", - "requires": { - "@chainsafe/libp2p-noise": "^4.1.1", - "@ethereumjs/block": "4.2.1", - "@ethereumjs/blockchain": "6.2.1", - "@ethereumjs/common": "3.1.1", - "@ethereumjs/devp2p": "5.1.1", - "@ethereumjs/ethash": "2.0.4", - "@ethereumjs/evm": "1.3.1", - "@ethereumjs/rlp": "4.0.1", - "@ethereumjs/statemanager": "1.0.4", - "@ethereumjs/trie": "5.0.4", - "@ethereumjs/tx": "4.1.1", - "@ethereumjs/util": "8.0.5", - "@ethereumjs/vm": "6.4.1", - "@types/body-parser": "^1.19.2", - "@types/connect": "^3.4.35", - "@types/fs-extra": "^9.0.13", - "@types/jwt-simple": "^0.5.33", - "@types/yargs": "^17.0.24", - "abstract-level": "^1.0.3", - "body-parser": "^1.19.2", - "c-kzg": "^2.0.4", - "chalk": "^4.1.2", - "connect": "^3.7.0", - "constants-browserify": "^1.0.0", - "cors": "^2.8.5", - "crypto-browserify": "^3.12.0", - "debug": "^4.3.3", - "ethereum-cryptography": "^2.0.0", - "file-replace-loader": "^1.2.0", - "fs-extra": "^10.1.0", - "it-pair": "^1.0.0", - "it-pipe": "^1.1.0", - "it-pushable": "^1.4.2", - "jayson": "^4.0.0", - "jwt-simple": "^0.5.6", - "level": "^8.0.0", - "libp2p": "^0.30.7", - "libp2p-bootstrap": "^0.14.0", - "libp2p-interfaces": "^1.2.0", - "libp2p-kad-dht": "^0.20.6", - "libp2p-mplex": "^0.10.2", - "libp2p-tcp": "^0.15.3", - "libp2p-websockets": "^0.15.1", - "memory-level": "^1.0.0", - "multiaddr": "^10.0.1", - "os-browserify": "^0.3.0", - "peer-id": "^0.14.3", - "pino": "^5.8.0", - "process": "^0.11.10", - "qheap": "^1.4.0", - "stream-browserify": "^3.0.0", - "supertest": "^6.1.3", - "superwstest": "^2.0.1", - "testdouble": "^3.16.6", - "testdouble-timers": "^0.1.1", - "util": "^0.12.4", - "webpack": "^5.55.1", - "webpack-cli": "^4.8.0", - "winston": "^3.3.3", - "winston-daily-rotate-file": "^4.5.5", - "yargs": "^17.7.1" - }, - "dependencies": { - "cliui": { - "version": "8.0.1", - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - } - }, - "emoji-regex": { - "version": "8.0.0" - }, - "is-fullwidth-code-point": { - "version": "3.0.0" - }, - "string-width": { - "version": "4.2.3", - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "yargs": { - "version": "17.7.1", - "requires": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - } - }, - "yargs-parser": { - "version": "21.1.1" - } - } - }, - "@ethereumjs/common": { - "version": "file:packages/common", - "requires": { - "@ethereumjs/util": "^8.0.5", - "crc-32": "^1.2.0" - } - }, - "@ethereumjs/devp2p": { - "version": "file:packages/devp2p", - "requires": { - "@ethereumjs/block": "^4.2.1", - "@ethereumjs/common": "^3.1.1", - "@ethereumjs/rlp": "^4.0.1", - "@ethereumjs/tx": "^4.1.1", - "@ethereumjs/util": "^8.0.5", - "@scure/base": "1.1.1", - "@types/chalk": "^2.2.0", - "@types/debug": "^4.1.4", - "@types/ip": "^1.1.0", - "@types/k-bucket": "^5.0.0", - "@types/ms": "^0.7.30", - "chalk": "^2.4.2", - "debug": "^4.3.3", - "ethereum-cryptography": "^2.0.0", - "k-bucket": "^5.0.0", - "lru-cache": "^7.18.3", - "ms": "^0.7.1", - "multiaddr": "^10.0.1", - "scanf": "^1.1.2", - "snappyjs": "^0.6.1", - "testdouble": "^3.8.2" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "color-convert": { - "version": "1.9.3", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "dev": true - }, - "has-flag": { - "version": "3.0.0", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "@ethereumjs/ethash": { - "version": "file:packages/ethash", - "requires": { - "@ethereumjs/block": "^4.2.1", - "@ethereumjs/common": "^3.1.1", - "@ethereumjs/rlp": "^4.0.1", - "@ethereumjs/util": "^8.0.5", - "bigint-crypto-utils": "^3.0.23", - "ethereum-cryptography": "^2.0.0" - } - }, - "@ethereumjs/evm": { - "version": "file:packages/evm", - "requires": { - "@ethereumjs/common": "^3.1.1", - "@ethereumjs/statemanager": "^1.0.4", - "@ethereumjs/util": "^8.0.5", - "@ethersproject/abi": "^5.0.12", - "@types/benchmark": "^1.0.33", - "@types/core-js": "^2.5.0", - "@types/minimist": "^1.2.2", - "@types/node-dir": "^0.0.34", - "benchmark": "^2.1.4", - "c-kzg": "^2.0.4", - "debug": "^4.3.3", - "ethereum-cryptography": "^2.0.0", - "level": "^8.0.0", - "mcl-wasm": "^0.7.1", - "memory-level": "^1.0.0", - "minimist": "^1.2.5", - "node-dir": "^0.1.17", - "rustbn.js": "~0.2.0", - "solc": "^0.8.1" - } - }, - "@ethereumjs/rlp": { - "version": "file:packages/rlp" - }, - "@ethereumjs/statemanager": { - "version": "file:packages/statemanager", - "requires": { - "@ethereumjs/block": "^4.2.1", - "@ethereumjs/common": "^3.1.1", - "@ethereumjs/rlp": "^4.0.1", - "@ethereumjs/trie": "^5.0.4", - "@ethereumjs/util": "^8.0.5", - "@types/node": "^16.11.7", - "@types/tape": "^4.13.2", - "debug": "^4.3.3", - "eslint": "^8.0.0", - "ethereum-cryptography": "^2.0.0", - "ethers": "^5.7.1", - "functional-red-black-tree": "^1.0.1", - "js-sdsl": "^4.1.4", - "karma": "^6.3.2", - "karma-chrome-launcher": "^3.1.0", - "karma-firefox-launcher": "^2.1.0", - "karma-tap": "^4.2.0", - "karma-typescript": "^5.5.3", - "lru-cache": "^7.18.3", - "nyc": "^15.1.0", - "standard": "^10.0.0", - "tape": "^5.3.1", - "ts-node": "^10.2.1", - "typescript": "^4.4.2" - } - }, - "@ethereumjs/trie": { - "version": "file:packages/trie", - "requires": { - "@ethereumjs/rlp": "^4.0.1", - "@ethereumjs/util": "^8.0.5", - "@types/benchmark": "^1.0.33", - "@types/readable-stream": "^2.3.13", - "0x": "^4.9.1", - "abstract-level": "^1.0.3", - "ethereum-cryptography": "^2.0.0", - "level": "^8.0.0", - "level-legacy": "npm:level@^7.0.0", - "level-mem": "^6.0.1", - "levelup": "^5.1.1", - "lmdb": "^2.5.3", - "lru-cache": "^7.18.3", - "memory-level": "^1.0.0", - "micro-bmark": "0.2.0", - "readable-stream": "^3.6.0" - }, - "dependencies": { - "readable-stream": { - "version": "3.6.0", - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } - } - }, - "@ethereumjs/tx": { - "version": "file:packages/tx", - "requires": { - "@chainsafe/ssz": "^0.11.0", - "@ethereumjs/common": "^3.1.1", - "@ethereumjs/rlp": "^4.0.1", - "@ethereumjs/util": "^8.0.5", - "@types/minimist": "^1.2.0", - "@types/node-dir": "^0.0.34", - "ethereum-cryptography": "^2.0.0", - "minimist": "^1.2.0", - "node-dir": "^0.1.16", - "testdouble": "^3.17.2" - } - }, - "@ethereumjs/util": { - "version": "file:packages/util", - "requires": { - "@chainsafe/ssz": "^0.11.0", - "@ethereumjs/rlp": "^4.0.1", - "@types/bn.js": "^5.1.0", - "@types/secp256k1": "^4.0.1", - "ethereum-cryptography": "^2.0.0" - } - }, - "@ethereumjs/vm": { - "version": "file:packages/vm", - "requires": { - "@ethereumjs/block": "^4.2.1", - "@ethereumjs/blockchain": "^6.2.1", - "@ethereumjs/common": "^3.1.1", - "@ethereumjs/evm": "^1.3.1", - "@ethereumjs/rlp": "^4.0.1", - "@ethereumjs/statemanager": "^1.0.4", - "@ethereumjs/trie": "^5.0.4", - "@ethereumjs/tx": "^4.1.1", - "@ethereumjs/util": "^8.0.5", - "@ethersproject/abi": "^5.0.12", - "@types/benchmark": "^1.0.33", - "@types/core-js": "^2.5.0", - "@types/minimist": "^1.2.2", - "@types/node-dir": "^0.0.34", - "benchmark": "^2.1.4", - "c-kzg": "^2.0.4", - "debug": "^4.3.3", - "ethereum-cryptography": "^2.0.0", - "mcl-wasm": "^0.7.1", - "minimist": "^1.2.5", - "node-dir": "^0.1.17", - "nyc": "^15.1.0", - "prettier": "^2.0.5", - "rustbn.js": "~0.2.0", - "solc": "^0.8.1", - "standard": "^10.0.0", - "tape": "^5.3.1", - "ts-node": "^10.2.1", - "typedoc": "^0.22.4", - "typescript": "^4.4.2" - }, - "dependencies": { - "brace-expansion": { - "version": "2.0.1", - "dev": true, - "requires": { - "balanced-match": "^1.0.0" - } - }, - "glob": { - "version": "8.0.3", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" - } - }, - "minimatch": { - "version": "5.1.0", - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - }, - "typedoc": { - "version": "0.22.18", - "dev": true, - "requires": { - "glob": "^8.0.3", - "lunr": "^2.3.9", - "marked": "^4.0.16", - "minimatch": "^5.1.0", - "shiki": "^0.10.1" - } - } - } - }, - "@ethersproject/abi": { - "version": "5.7.0", - "requires": { - "@ethersproject/address": "^5.7.0", - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/constants": "^5.7.0", - "@ethersproject/hash": "^5.7.0", - "@ethersproject/keccak256": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/strings": "^5.7.0" - } - }, - "@ethersproject/abstract-provider": { - "version": "5.7.0", - "requires": { - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/networks": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/transactions": "^5.7.0", - "@ethersproject/web": "^5.7.0" - } - }, - "@ethersproject/abstract-signer": { - "version": "5.7.0", - "requires": { - "@ethersproject/abstract-provider": "^5.7.0", - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0" - } - }, - "@ethersproject/address": { - "version": "5.7.0", - "requires": { - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/keccak256": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/rlp": "^5.7.0" - } - }, - "@ethersproject/base64": { - "version": "5.7.0", - "requires": { - "@ethersproject/bytes": "^5.7.0" - } - }, - "@ethersproject/basex": { - "version": "5.7.0", - "requires": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/properties": "^5.7.0" - } - }, - "@ethersproject/bignumber": { - "version": "5.7.0", - "requires": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "bn.js": "^5.2.1" - } - }, - "@ethersproject/bytes": { - "version": "5.7.0", - "requires": { - "@ethersproject/logger": "^5.7.0" - } - }, - "@ethersproject/constants": { - "version": "5.7.0", - "requires": { - "@ethersproject/bignumber": "^5.7.0" - } - }, - "@ethersproject/contracts": { - "version": "5.7.0", - "requires": { - "@ethersproject/abi": "^5.7.0", - "@ethersproject/abstract-provider": "^5.7.0", - "@ethersproject/abstract-signer": "^5.7.0", - "@ethersproject/address": "^5.7.0", - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/constants": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/transactions": "^5.7.0" - } - }, - "@ethersproject/hash": { - "version": "5.7.0", - "requires": { - "@ethersproject/abstract-signer": "^5.7.0", - "@ethersproject/address": "^5.7.0", - "@ethersproject/base64": "^5.7.0", - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/keccak256": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/strings": "^5.7.0" - } - }, - "@ethersproject/hdnode": { - "version": "5.7.0", - "requires": { - "@ethersproject/abstract-signer": "^5.7.0", - "@ethersproject/basex": "^5.7.0", - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/pbkdf2": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/sha2": "^5.7.0", - "@ethersproject/signing-key": "^5.7.0", - "@ethersproject/strings": "^5.7.0", - "@ethersproject/transactions": "^5.7.0", - "@ethersproject/wordlists": "^5.7.0" - } - }, - "@ethersproject/json-wallets": { - "version": "5.7.0", - "requires": { - "@ethersproject/abstract-signer": "^5.7.0", - "@ethersproject/address": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/hdnode": "^5.7.0", - "@ethersproject/keccak256": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/pbkdf2": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/random": "^5.7.0", - "@ethersproject/strings": "^5.7.0", - "@ethersproject/transactions": "^5.7.0", - "aes-js": "3.0.0", - "scrypt-js": "3.0.1" - } - }, - "@ethersproject/keccak256": { - "version": "5.7.0", - "requires": { - "@ethersproject/bytes": "^5.7.0", - "js-sha3": "0.8.0" - } - }, - "@ethersproject/logger": { - "version": "5.7.0" - }, - "@ethersproject/networks": { - "version": "5.7.1", - "requires": { - "@ethersproject/logger": "^5.7.0" - } - }, - "@ethersproject/pbkdf2": { - "version": "5.7.0", - "requires": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/sha2": "^5.7.0" - } - }, - "@ethersproject/properties": { - "version": "5.7.0", - "requires": { - "@ethersproject/logger": "^5.7.0" - } - }, - "@ethersproject/providers": { - "version": "5.7.2", - "requires": { - "@ethersproject/abstract-provider": "^5.7.0", - "@ethersproject/abstract-signer": "^5.7.0", - "@ethersproject/address": "^5.7.0", - "@ethersproject/base64": "^5.7.0", - "@ethersproject/basex": "^5.7.0", - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/constants": "^5.7.0", - "@ethersproject/hash": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/networks": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/random": "^5.7.0", - "@ethersproject/rlp": "^5.7.0", - "@ethersproject/sha2": "^5.7.0", - "@ethersproject/strings": "^5.7.0", - "@ethersproject/transactions": "^5.7.0", - "@ethersproject/web": "^5.7.0", - "bech32": "1.1.4", - "ws": "7.4.6" - }, - "dependencies": { - "ws": { - "version": "7.4.6", - "requires": {} - } - } - }, - "@ethersproject/random": { - "version": "5.7.0", - "requires": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0" - } - }, - "@ethersproject/rlp": { - "version": "5.7.0", - "requires": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0" - } - }, - "@ethersproject/sha2": { - "version": "5.7.0", - "requires": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "hash.js": "1.1.7" - } - }, - "@ethersproject/signing-key": { - "version": "5.7.0", - "requires": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "bn.js": "^5.2.1", - "elliptic": "6.5.4", - "hash.js": "1.1.7" - } - }, - "@ethersproject/solidity": { - "version": "5.7.0", - "requires": { - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/keccak256": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/sha2": "^5.7.0", - "@ethersproject/strings": "^5.7.0" - } - }, - "@ethersproject/strings": { - "version": "5.7.0", - "requires": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/constants": "^5.7.0", - "@ethersproject/logger": "^5.7.0" - } - }, - "@ethersproject/transactions": { - "version": "5.7.0", - "requires": { - "@ethersproject/address": "^5.7.0", - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/constants": "^5.7.0", - "@ethersproject/keccak256": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/rlp": "^5.7.0", - "@ethersproject/signing-key": "^5.7.0" - } - }, - "@ethersproject/units": { - "version": "5.7.0", - "requires": { - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/constants": "^5.7.0", - "@ethersproject/logger": "^5.7.0" - } - }, - "@ethersproject/wallet": { - "version": "5.7.0", - "requires": { - "@ethersproject/abstract-provider": "^5.7.0", - "@ethersproject/abstract-signer": "^5.7.0", - "@ethersproject/address": "^5.7.0", - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/hash": "^5.7.0", - "@ethersproject/hdnode": "^5.7.0", - "@ethersproject/json-wallets": "^5.7.0", - "@ethersproject/keccak256": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/random": "^5.7.0", - "@ethersproject/signing-key": "^5.7.0", - "@ethersproject/transactions": "^5.7.0", - "@ethersproject/wordlists": "^5.7.0" - } - }, - "@ethersproject/web": { - "version": "5.7.1", - "requires": { - "@ethersproject/base64": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/strings": "^5.7.0" - } - }, - "@ethersproject/wordlists": { - "version": "5.7.0", - "requires": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/hash": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/strings": "^5.7.0" - } - }, - "@humanwhocodes/config-array": { - "version": "0.10.7", - "dev": true, - "requires": { - "@humanwhocodes/object-schema": "^1.2.1", - "debug": "^4.1.1", - "minimatch": "^3.0.4" - } - }, - "@humanwhocodes/gitignore-to-minimatch": { - "version": "1.0.2", - "dev": true - }, - "@humanwhocodes/object-schema": { - "version": "1.2.1", - "dev": true - }, - "@istanbuljs/load-nyc-config": { - "version": "1.1.0", - "dev": true, - "requires": { - "camelcase": "^5.3.1", - "find-up": "^4.1.0", - "get-package-type": "^0.1.0", - "js-yaml": "^3.13.1", - "resolve-from": "^5.0.0" - }, - "dependencies": { - "argparse": { - "version": "1.0.10", - "dev": true, - "requires": { - "sprintf-js": "~1.0.2" - } - }, - "find-up": { - "version": "4.1.0", - "dev": true, - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "js-yaml": { - "version": "3.14.1", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - }, - "locate-path": { - "version": "5.0.0", - "dev": true, - "requires": { - "p-locate": "^4.1.0" - } - }, - "p-limit": { - "version": "2.3.0", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "4.1.0", - "dev": true, - "requires": { - "p-limit": "^2.2.0" - } - }, - "resolve-from": { - "version": "5.0.0", - "dev": true - }, - "sprintf-js": { - "version": "1.0.3", - "dev": true - } - } - }, - "@istanbuljs/schema": { - "version": "0.1.3", - "dev": true - }, - "@jridgewell/gen-mapping": { - "version": "0.1.1", - "dev": true, - "requires": { - "@jridgewell/set-array": "^1.0.0", - "@jridgewell/sourcemap-codec": "^1.4.10" - } - }, - "@jridgewell/resolve-uri": { - "version": "3.1.0", - "dev": true - }, - "@jridgewell/set-array": { - "version": "1.1.2", - "dev": true - }, - "@jridgewell/source-map": { - "version": "0.3.2", - "dev": true, - "requires": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "dependencies": { - "@jridgewell/gen-mapping": { - "version": "0.3.2", - "dev": true, - "requires": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - } - } - } - }, - "@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "dev": true - }, - "@jridgewell/trace-mapping": { - "version": "0.3.17", - "dev": true, - "requires": { - "@jridgewell/resolve-uri": "3.1.0", - "@jridgewell/sourcemap-codec": "1.4.14" - } - }, - "@motrix/nat-api": { - "version": "0.3.2", - "requires": { - "async": "^3.2.0", - "debug": "^4.3.1", - "default-gateway": "^6.0.3", - "request": "^2.88.2", - "unordered-array-remove": "^1.0.2", - "xml2js": "^0.4.23" - } - }, - "@multiformats/base-x": { - "version": "4.0.1" - }, - "@noble/curves": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.0.0.tgz", - "integrity": "sha512-2upgEu0iLiDVDZkNLeFV2+ht0BAVgQnEmCk6JsOch9Rp8xfkMCbvbAZlA2pBHQc73dbl+vFOXfqkf4uemdn0bw==", - "requires": { - "@noble/hashes": "1.3.0" - } - }, - "@noble/ed25519": { - "version": "1.7.1" - }, - "@noble/hashes": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.0.tgz", - "integrity": "sha512-ilHEACi9DwqJB0pw7kv+Apvh50jiiSyR/cQ3y4W7lOR5mhvn/50FLUfsnfJz0BDZtl/RR16kXvptiv6q1msYZg==" - }, - "@noble/secp256k1": { - "version": "1.6.3" - }, - "@nodelib/fs.scandir": { - "version": "2.1.5", - "dev": true, - "requires": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - } - }, - "@nodelib/fs.stat": { - "version": "2.0.5", - "dev": true - }, - "@nodelib/fs.walk": { - "version": "1.2.8", - "dev": true, - "requires": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - } - }, - "@protobufjs/aspromise": { - "version": "1.1.2" - }, - "@protobufjs/base64": { - "version": "1.1.2" - }, - "@protobufjs/codegen": { - "version": "2.0.4" - }, - "@protobufjs/eventemitter": { - "version": "1.1.0" - }, - "@protobufjs/fetch": { - "version": "1.1.0", - "requires": { - "@protobufjs/aspromise": "^1.1.1", - "@protobufjs/inquire": "^1.1.0" - } - }, - "@protobufjs/float": { - "version": "1.0.2" - }, - "@protobufjs/inquire": { - "version": "1.1.0" - }, - "@protobufjs/path": { - "version": "1.1.2" - }, - "@protobufjs/pool": { - "version": "1.1.0" - }, - "@protobufjs/utf8": { - "version": "1.1.0" - }, - "@scure/base": { - "version": "1.1.1" - }, - "@scure/bip32": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.3.0.tgz", - "integrity": "sha512-bcKpo1oj54hGholplGLpqPHRbIsnbixFtc06nwuNM5/dwSXOq/AAYoIBRsBmnZJSdfeNW5rnff7NTAz3ZCqR9Q==", - "requires": { - "@noble/curves": "~1.0.0", - "@noble/hashes": "~1.3.0", - "@scure/base": "~1.1.0" - } - }, - "@scure/bip39": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.2.0.tgz", - "integrity": "sha512-SX/uKq52cuxm4YFXWFaVByaSHJh2w3BnokVSeUJVCv6K7WulT9u2BuNRBhuFl8vAuYnzx9bEu9WgpcNYTrYieg==", - "requires": { - "@noble/hashes": "~1.3.0", - "@scure/base": "~1.1.0" - } - }, - "@sinonjs/commons": { - "version": "1.8.3", - "requires": { - "type-detect": "4.0.8" - } - }, - "@sinonjs/fake-timers": { - "version": "6.0.1", - "requires": { - "@sinonjs/commons": "^1.7.0" - } - }, - "@sinonjs/samsam": { - "version": "5.3.1", - "requires": { - "@sinonjs/commons": "^1.6.0", - "lodash.get": "^4.4.2", - "type-detect": "^4.0.8" - } - }, - "@sinonjs/text-encoding": { - "version": "0.7.2" - }, - "@socket.io/component-emitter": { - "version": "3.1.0", - "dev": true - }, - "@stablelib/aead": { - "version": "1.0.1" - }, - "@stablelib/binary": { - "version": "1.0.1", - "requires": { - "@stablelib/int": "^1.0.1" - } - }, - "@stablelib/bytes": { - "version": "1.0.1" - }, - "@stablelib/chacha": { - "version": "1.0.1", - "requires": { - "@stablelib/binary": "^1.0.1", - "@stablelib/wipe": "^1.0.1" - } - }, - "@stablelib/chacha20poly1305": { - "version": "1.0.1", - "requires": { - "@stablelib/aead": "^1.0.1", - "@stablelib/binary": "^1.0.1", - "@stablelib/chacha": "^1.0.1", - "@stablelib/constant-time": "^1.0.1", - "@stablelib/poly1305": "^1.0.1", - "@stablelib/wipe": "^1.0.1" - } - }, - "@stablelib/constant-time": { - "version": "1.0.1" - }, - "@stablelib/hash": { - "version": "1.0.1" - }, - "@stablelib/hkdf": { - "version": "1.0.1", - "requires": { - "@stablelib/hash": "^1.0.1", - "@stablelib/hmac": "^1.0.1", - "@stablelib/wipe": "^1.0.1" - } - }, - "@stablelib/hmac": { - "version": "1.0.1", - "requires": { - "@stablelib/constant-time": "^1.0.1", - "@stablelib/hash": "^1.0.1", - "@stablelib/wipe": "^1.0.1" - } - }, - "@stablelib/int": { - "version": "1.0.1" - }, - "@stablelib/keyagreement": { - "version": "1.0.1", - "requires": { - "@stablelib/bytes": "^1.0.1" - } - }, - "@stablelib/poly1305": { - "version": "1.0.1", - "requires": { - "@stablelib/constant-time": "^1.0.1", - "@stablelib/wipe": "^1.0.1" - } - }, - "@stablelib/random": { - "version": "1.0.2", - "requires": { - "@stablelib/binary": "^1.0.1", - "@stablelib/wipe": "^1.0.1" - } - }, - "@stablelib/sha256": { - "version": "1.0.1", - "requires": { - "@stablelib/binary": "^1.0.1", - "@stablelib/hash": "^1.0.1", - "@stablelib/wipe": "^1.0.1" - } - }, - "@stablelib/wipe": { - "version": "1.0.1" - }, - "@stablelib/x25519": { - "version": "1.0.3", - "requires": { - "@stablelib/keyagreement": "^1.0.1", - "@stablelib/random": "^1.0.2", - "@stablelib/wipe": "^1.0.1" - } - }, - "@tsconfig/node10": { - "version": "1.0.9", - "dev": true - }, - "@tsconfig/node12": { - "version": "1.0.11", - "dev": true - }, - "@tsconfig/node14": { - "version": "1.0.3", - "dev": true - }, - "@tsconfig/node16": { - "version": "1.0.3", - "dev": true - }, - "@types/async": { - "version": "2.4.2", - "dev": true - }, - "@types/benchmark": { - "version": "1.0.33", - "dev": true - }, - "@types/bl": { - "version": "2.1.0", - "requires": { - "@types/node": "*" - } - }, - "@types/bn.js": { - "version": "5.1.1", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/body-parser": { - "version": "1.19.2", - "dev": true, - "requires": { - "@types/connect": "*", - "@types/node": "*" - } - }, - "@types/chalk": { - "version": "2.2.0", - "dev": true, - "requires": { - "chalk": "*" - } - }, - "@types/connect": { - "version": "3.4.35", - "requires": { - "@types/node": "*" - } - }, - "@types/cookie": { - "version": "0.4.1", - "dev": true - }, - "@types/cookiejar": { - "version": "2.1.2", - "dev": true - }, - "@types/core-js": { - "version": "2.5.5", - "dev": true - }, - "@types/cors": { - "version": "2.8.12", - "dev": true - }, - "@types/debug": { - "version": "4.1.7", - "dev": true, - "requires": { - "@types/ms": "*" - } - }, - "@types/eslint": { - "version": "8.4.7", - "dev": true, - "requires": { - "@types/estree": "*", - "@types/json-schema": "*" - } - }, - "@types/eslint-scope": { - "version": "3.7.4", - "dev": true, - "requires": { - "@types/eslint": "*", - "@types/estree": "*" - } - }, - "@types/estree": { - "version": "0.0.51", - "dev": true - }, - "@types/fs-extra": { - "version": "9.0.13", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/glob": { - "version": "7.2.0", - "dev": true, - "requires": { - "@types/minimatch": "*", - "@types/node": "*" - } - }, - "@types/ip": { - "version": "1.1.0", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/istanbul-lib-coverage": { - "version": "2.0.4", - "dev": true - }, - "@types/json-schema": { - "version": "7.0.11", - "dev": true - }, - "@types/json5": { - "version": "0.0.29", - "dev": true - }, - "@types/jwt-simple": { - "version": "0.5.33", - "dev": true - }, - "@types/k-bucket": { - "version": "5.0.1", - "requires": { - "@types/node": "*" - } - }, - "@types/level-errors": { - "version": "3.0.0", - "dev": true - }, - "@types/long": { - "version": "4.0.2" - }, - "@types/minimatch": { - "version": "3.0.5" - }, - "@types/minimist": { - "version": "1.2.2", - "dev": true - }, - "@types/ms": { - "version": "0.7.31", - "dev": true - }, - "@types/node": { - "version": "16.11.49" - }, - "@types/node-dir": { - "version": "0.0.34", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/readable-stream": { - "version": "2.3.14", - "requires": { - "@types/node": "*", - "safe-buffer": "*" - } - }, - "@types/retry": { - "version": "0.12.0" - }, - "@types/secp256k1": { - "version": "4.0.3", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/superagent": { - "version": "4.1.15", - "dev": true, - "requires": { - "@types/cookiejar": "*", - "@types/node": "*" - } - }, - "@types/supertest": { - "version": "2.0.12", - "dev": true, - "requires": { - "@types/superagent": "*" - } - }, - "@types/tape": { - "version": "4.13.2", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/ws": { - "version": "7.4.7", - "requires": { - "@types/node": "*" - } - }, - "@types/yargs": { - "version": "17.0.24", - "dev": true, - "requires": { - "@types/yargs-parser": "*" - } - }, - "@types/yargs-parser": { - "version": "21.0.0", - "dev": true - }, - "@typescript-eslint/eslint-plugin": { - "version": "5.33.1", - "dev": true, - "requires": { - "@typescript-eslint/scope-manager": "5.33.1", - "@typescript-eslint/type-utils": "5.33.1", - "@typescript-eslint/utils": "5.33.1", - "debug": "^4.3.4", - "functional-red-black-tree": "^1.0.1", - "ignore": "^5.2.0", - "regexpp": "^3.2.0", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - } - }, - "@typescript-eslint/parser": { - "version": "5.33.1", - "dev": true, - "requires": { - "@typescript-eslint/scope-manager": "5.33.1", - "@typescript-eslint/types": "5.33.1", - "@typescript-eslint/typescript-estree": "5.33.1", - "debug": "^4.3.4" - } - }, - "@typescript-eslint/scope-manager": { - "version": "5.33.1", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.33.1", - "@typescript-eslint/visitor-keys": "5.33.1" - } - }, - "@typescript-eslint/type-utils": { - "version": "5.33.1", - "dev": true, - "requires": { - "@typescript-eslint/utils": "5.33.1", - "debug": "^4.3.4", - "tsutils": "^3.21.0" - } - }, - "@typescript-eslint/types": { - "version": "5.33.1", - "dev": true - }, - "@typescript-eslint/typescript-estree": { - "version": "5.33.1", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.33.1", - "@typescript-eslint/visitor-keys": "5.33.1", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - } - }, - "@typescript-eslint/utils": { - "version": "5.33.1", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.9", - "@typescript-eslint/scope-manager": "5.33.1", - "@typescript-eslint/types": "5.33.1", - "@typescript-eslint/typescript-estree": "5.33.1", - "eslint-scope": "^5.1.1", - "eslint-utils": "^3.0.0" - } - }, - "@typescript-eslint/visitor-keys": { - "version": "5.33.1", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.33.1", - "eslint-visitor-keys": "^3.3.0" - } - }, - "@webassemblyjs/ast": { - "version": "1.11.1", - "dev": true, - "requires": { - "@webassemblyjs/helper-numbers": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1" - } - }, - "@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.1", - "dev": true - }, - "@webassemblyjs/helper-api-error": { - "version": "1.11.1", - "dev": true - }, - "@webassemblyjs/helper-buffer": { - "version": "1.11.1", - "dev": true - }, - "@webassemblyjs/helper-numbers": { - "version": "1.11.1", - "dev": true, - "requires": { - "@webassemblyjs/floating-point-hex-parser": "1.11.1", - "@webassemblyjs/helper-api-error": "1.11.1", - "@xtuc/long": "4.2.2" - } - }, - "@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.1", - "dev": true - }, - "@webassemblyjs/helper-wasm-section": { - "version": "1.11.1", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1" - } - }, - "@webassemblyjs/ieee754": { - "version": "1.11.1", - "dev": true, - "requires": { - "@xtuc/ieee754": "^1.2.0" - } - }, - "@webassemblyjs/leb128": { - "version": "1.11.1", - "dev": true, - "requires": { - "@xtuc/long": "4.2.2" - } - }, - "@webassemblyjs/utf8": { - "version": "1.11.1", - "dev": true - }, - "@webassemblyjs/wasm-edit": { - "version": "1.11.1", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/helper-wasm-section": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1", - "@webassemblyjs/wasm-opt": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1", - "@webassemblyjs/wast-printer": "1.11.1" - } - }, - "@webassemblyjs/wasm-gen": { - "version": "1.11.1", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/ieee754": "1.11.1", - "@webassemblyjs/leb128": "1.11.1", - "@webassemblyjs/utf8": "1.11.1" - } - }, - "@webassemblyjs/wasm-opt": { - "version": "1.11.1", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1" - } - }, - "@webassemblyjs/wasm-parser": { - "version": "1.11.1", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-api-error": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/ieee754": "1.11.1", - "@webassemblyjs/leb128": "1.11.1", - "@webassemblyjs/utf8": "1.11.1" - } - }, - "@webassemblyjs/wast-printer": { - "version": "1.11.1", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.1", - "@xtuc/long": "4.2.2" - } - }, - "@webpack-cli/configtest": { - "version": "1.2.0", - "dev": true, - "requires": {} - }, - "@webpack-cli/info": { - "version": "1.5.0", - "dev": true, - "requires": { - "envinfo": "^7.7.3" - } - }, - "@webpack-cli/serve": { - "version": "1.7.0", - "dev": true, - "requires": {} - }, - "@xtuc/ieee754": { - "version": "1.2.0", - "dev": true - }, - "@xtuc/long": { - "version": "4.2.2", - "dev": true - }, - "@zxing/text-encoding": { - "version": "0.9.0", - "optional": true - }, - "0x": { - "version": "4.11.0", - "dev": true, - "requires": { - "ajv": "^6.9.2", - "browserify": "^16.2.3", - "concat-stream": "^1.5.2", - "d3-fg": "^6.14.0", - "debounce": "^1.2.0", - "debug": "^4.1.1", - "end-of-stream": "^1.1.0", - "env-string": "^1.0.0", - "escape-string-regexp": "^1.0.5", - "execspawn": "^1.0.1", - "has-unicode": "^2.0.1", - "hsl-to-rgb-for-reals": "^1.1.0", - "jsonstream2": "^1.1.2", - "make-dir": "^1.3.0", - "minimist": "^1.2.0", - "morphdom": "^2.3.3", - "nanohtml": "^1.4.0", - "on-net-listen": "^1.1.0", - "opn": "^5.4.0", - "perf-sym": "^2.0.3", - "pump": "^3.0.0", - "pumpify": "^1.4.0", - "semver": "^5.5.1", - "single-line-log": "^1.0.1", - "split2": "^3.1.0", - "tachyons": "^4.9.1", - "through2": "^2.0.5", - "which": "^1.2.4" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "dev": true - } - } - }, - "abort-controller": { - "version": "3.0.0", - "requires": { - "event-target-shim": "^5.0.0" - } - }, - "abortable-iterator": { - "version": "3.0.2", - "requires": { - "get-iterator": "^1.0.2" - } - }, - "abstract-level": { - "version": "1.0.3", - "requires": { - "buffer": "^6.0.3", - "catering": "^2.1.0", - "is-buffer": "^2.0.5", - "level-supports": "^4.0.0", - "level-transcoder": "^1.0.1", - "module-error": "^1.0.1", - "queue-microtask": "^1.2.3" - } - }, - "abstract-leveldown": { - "version": "7.2.0", - "dev": true, - "requires": { - "buffer": "^6.0.3", - "catering": "^2.0.0", - "is-buffer": "^2.0.5", - "level-concat-iterator": "^3.0.0", - "level-supports": "^2.0.1", - "queue-microtask": "^1.2.3" - }, - "dependencies": { - "level-supports": { - "version": "2.1.0", - "dev": true - } - } - }, - "accepts": { - "version": "1.3.8", - "dev": true, - "requires": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - } - }, - "acorn": { - "version": "8.8.0", - "dev": true - }, - "acorn-import-assertions": { - "version": "1.8.0", - "dev": true, - "requires": {} - }, - "acorn-jsx": { - "version": "5.3.2", - "dev": true, - "requires": {} - }, - "acorn-node": { - "version": "1.8.2", - "dev": true, - "requires": { - "acorn": "^7.0.0", - "acorn-walk": "^7.0.0", - "xtend": "^4.0.2" - }, - "dependencies": { - "acorn": { - "version": "7.4.1", - "dev": true - } - } - }, - "acorn-walk": { - "version": "7.2.0", - "dev": true - }, - "aes-js": { - "version": "3.0.0" - }, - "aggregate-error": { - "version": "3.1.0", - "requires": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - } - }, - "ajv": { - "version": "6.12.6", - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ajv-keywords": { - "version": "3.5.2", - "dev": true, - "requires": {} - }, - "ansi-escapes": { - "version": "4.3.2", - "dev": true, - "requires": { - "type-fest": "^0.21.3" - }, - "dependencies": { - "type-fest": { - "version": "0.21.3", - "dev": true - } - } - }, - "ansi-regex": { - "version": "5.0.1" - }, - "ansi-styles": { - "version": "4.3.0", - "requires": { - "color-convert": "^2.0.1" - } - }, - "ansicolors": { - "version": "0.2.1", - "dev": true - }, - "any-signal": { - "version": "2.1.2", - "requires": { - "abort-controller": "^3.0.0", - "native-abort-controller": "^1.0.3" - } - }, - "anymatch": { - "version": "3.1.2", - "dev": true, - "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - } - }, - "append-transform": { - "version": "2.0.0", - "dev": true, - "requires": { - "default-require-extensions": "^3.0.0" - } - }, - "archy": { - "version": "1.0.0", - "dev": true - }, - "arg": { - "version": "4.1.3", - "dev": true - }, - "argparse": { - "version": "2.0.1", - "dev": true - }, - "aria-query": { - "version": "4.2.2", - "dev": true, - "requires": { - "@babel/runtime": "^7.10.2", - "@babel/runtime-corejs3": "^7.10.2" - } - }, - "array-includes": { - "version": "3.1.5", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.19.5", - "get-intrinsic": "^1.1.1", - "is-string": "^1.0.7" - } - }, - "array-union": { - "version": "2.1.0", - "dev": true - }, - "array.prototype.every": { - "version": "1.1.3", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.0", - "is-string": "^1.0.7" - } - }, - "array.prototype.find": { - "version": "2.2.0", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.4", - "es-shim-unscopables": "^1.0.0" - } - }, - "array.prototype.flat": { - "version": "1.3.0", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.2", - "es-shim-unscopables": "^1.0.0" - } - }, - "asap": { - "version": "2.0.6", - "dev": true - }, - "asn1": { - "version": "0.2.6", - "requires": { - "safer-buffer": "~2.1.0" - } - }, - "asn1.js": { - "version": "5.4.1", - "requires": { - "bn.js": "^4.0.0", - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0", - "safer-buffer": "^2.1.0" - }, - "dependencies": { - "bn.js": { - "version": "4.12.0" - } - } - }, - "assert": { - "version": "1.5.0", - "dev": true, - "requires": { - "object-assign": "^4.1.1", - "util": "0.10.3" - }, - "dependencies": { - "inherits": { - "version": "2.0.1", - "dev": true - }, - "util": { - "version": "0.10.3", - "dev": true, - "requires": { - "inherits": "2.0.1" - } - } - } - }, - "assert-plus": { - "version": "1.0.0" - }, - "assertion-error": { - "version": "1.1.0" - }, - "ast-types-flow": { - "version": "0.0.7", - "dev": true - }, - "astral-regex": { - "version": "2.0.0", - "dev": true - }, - "async": { - "version": "3.2.4" - }, - "asynckit": { - "version": "0.4.0" - }, - "atomic-sleep": { - "version": "1.0.0", - "dev": true - }, - "available-typed-arrays": { - "version": "1.0.5" - }, - "aws-sign2": { - "version": "0.7.0" - }, - "aws4": { - "version": "1.11.0" - }, - "axe-core": { - "version": "4.4.3", - "dev": true - }, - "axobject-query": { - "version": "2.2.0", - "dev": true - }, - "babel-code-frame": { - "version": "6.26.0", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "esutils": "^2.0.2", - "js-tokens": "^3.0.2" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "dev": true - }, - "ansi-styles": { - "version": "2.2.1", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } - }, - "js-tokens": { - "version": "3.0.2", - "dev": true - }, - "strip-ansi": { - "version": "3.0.1", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "supports-color": { - "version": "2.0.0", - "dev": true - } - } - }, - "babel-plugin-polyfill-corejs2": { - "version": "0.3.3", - "dev": true, - "requires": { - "@babel/compat-data": "^7.17.7", - "@babel/helper-define-polyfill-provider": "^0.3.3", - "semver": "^6.1.1" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "dev": true - } - } - }, - "babel-plugin-polyfill-corejs3": { - "version": "0.6.0", - "dev": true, - "requires": { - "@babel/helper-define-polyfill-provider": "^0.3.3", - "core-js-compat": "^3.25.1" - } - }, - "babel-plugin-polyfill-regenerator": { - "version": "0.4.1", - "dev": true, - "requires": { - "@babel/helper-define-polyfill-provider": "^0.3.3" - } - }, - "babel-polyfill": { - "version": "6.26.0", - "dev": true, - "requires": { - "babel-runtime": "^6.26.0", - "core-js": "^2.5.0", - "regenerator-runtime": "^0.10.5" - }, - "dependencies": { - "regenerator-runtime": { - "version": "0.10.5", - "dev": true - } - } - }, - "babel-runtime": { - "version": "6.26.0", - "dev": true, - "requires": { - "core-js": "^2.4.0", - "regenerator-runtime": "^0.11.0" - }, - "dependencies": { - "regenerator-runtime": { - "version": "0.11.1", - "dev": true - } - } - }, - "balanced-match": { - "version": "1.0.2" - }, - "base32.js": { - "version": "0.1.0" - }, - "base64-js": { - "version": "1.5.1" - }, - "base64id": { - "version": "2.0.0", - "dev": true - }, - "bcrypt-pbkdf": { - "version": "1.0.2", - "requires": { - "tweetnacl": "^0.14.3" - } - }, - "bech32": { - "version": "1.1.4" - }, - "benchmark": { - "version": "2.1.4", - "dev": true, - "requires": { - "lodash": "^4.17.4", - "platform": "^1.3.3" - } - }, - "big.js": { - "version": "5.2.2", - "dev": true - }, - "bigint-crypto-utils": { - "version": "3.1.7", - "requires": { - "bigint-mod-arith": "^3.1.0" - } - }, - "bigint-mod-arith": { - "version": "3.1.2" - }, - "bignumber.js": { - "version": "9.1.0" - }, - "binary-extensions": { - "version": "2.2.0", - "dev": true - }, - "bindings": { - "version": "1.5.0", - "requires": { - "file-uri-to-path": "1.0.0" - } - }, - "blakejs": { - "version": "1.2.1" - }, - "bn.js": { - "version": "5.2.1" - }, - "body-parser": { - "version": "1.20.1", - "requires": { - "bytes": "3.1.2", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.11.0", - "raw-body": "2.5.1", - "type-is": "~1.6.18", - "unpipe": "1.0.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0" - } - } - }, - "brace-expansion": { - "version": "1.1.11", - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "3.0.2", - "dev": true, - "requires": { - "fill-range": "^7.0.1" - } - }, - "brorand": { - "version": "1.1.0" - }, - "browser-level": { - "version": "1.0.1", - "requires": { - "abstract-level": "^1.0.2", - "catering": "^2.1.1", - "module-error": "^1.0.2", - "run-parallel-limit": "^1.1.0" - } - }, - "browser-pack": { - "version": "6.1.0", - "dev": true, - "requires": { - "combine-source-map": "~0.8.0", - "defined": "^1.0.0", - "JSONStream": "^1.0.3", - "safe-buffer": "^5.1.1", - "through2": "^2.0.0", - "umd": "^3.0.0" - } - }, - "browser-process-hrtime": { - "version": "0.1.3", - "dev": true - }, - "browser-resolve": { - "version": "2.0.0", - "dev": true, - "requires": { - "resolve": "^1.17.0" - } - }, - "browserify": { - "version": "16.5.2", - "dev": true, - "requires": { - "assert": "^1.4.0", - "browser-pack": "^6.0.1", - "browser-resolve": "^2.0.0", - "browserify-zlib": "~0.2.0", - "buffer": "~5.2.1", - "cached-path-relative": "^1.0.0", - "concat-stream": "^1.6.0", - "console-browserify": "^1.1.0", - "constants-browserify": "~1.0.0", - "crypto-browserify": "^3.0.0", - "defined": "^1.0.0", - "deps-sort": "^2.0.0", - "domain-browser": "^1.2.0", - "duplexer2": "~0.1.2", - "events": "^2.0.0", - "glob": "^7.1.0", - "has": "^1.0.0", - "htmlescape": "^1.1.0", - "https-browserify": "^1.0.0", - "inherits": "~2.0.1", - "insert-module-globals": "^7.0.0", - "JSONStream": "^1.0.3", - "labeled-stream-splicer": "^2.0.0", - "mkdirp-classic": "^0.5.2", - "module-deps": "^6.2.3", - "os-browserify": "~0.3.0", - "parents": "^1.0.1", - "path-browserify": "~0.0.0", - "process": "~0.11.0", - "punycode": "^1.3.2", - "querystring-es3": "~0.2.0", - "read-only-stream": "^2.0.0", - "readable-stream": "^2.0.2", - "resolve": "^1.1.4", - "shasum": "^1.0.0", - "shell-quote": "^1.6.1", - "stream-browserify": "^2.0.0", - "stream-http": "^3.0.0", - "string_decoder": "^1.1.1", - "subarg": "^1.0.0", - "syntax-error": "^1.1.1", - "through2": "^2.0.0", - "timers-browserify": "^1.0.1", - "tty-browserify": "0.0.1", - "url": "~0.11.0", - "util": "~0.10.1", - "vm-browserify": "^1.0.0", - "xtend": "^4.0.0" - }, - "dependencies": { - "buffer": { - "version": "5.2.1", - "dev": true, - "requires": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4" - } - }, - "inherits": { - "version": "2.0.3", - "dev": true - }, - "stream-browserify": { - "version": "2.0.2", - "dev": true, - "requires": { - "inherits": "~2.0.1", - "readable-stream": "^2.0.2" - } - }, - "util": { - "version": "0.10.4", - "dev": true, - "requires": { - "inherits": "2.0.3" - } - } - } - }, - "browserify-aes": { - "version": "1.2.0", - "dev": true, - "requires": { - "buffer-xor": "^1.0.3", - "cipher-base": "^1.0.0", - "create-hash": "^1.1.0", - "evp_bytestokey": "^1.0.3", - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "browserify-cipher": { - "version": "1.0.1", - "dev": true, - "requires": { - "browserify-aes": "^1.0.4", - "browserify-des": "^1.0.0", - "evp_bytestokey": "^1.0.0" - } - }, - "browserify-des": { - "version": "1.0.2", - "dev": true, - "requires": { - "cipher-base": "^1.0.1", - "des.js": "^1.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "browserify-rsa": { - "version": "4.1.0", - "dev": true, - "requires": { - "bn.js": "^5.0.0", - "randombytes": "^2.0.1" - } - }, - "browserify-sign": { - "version": "4.2.1", - "dev": true, - "requires": { - "bn.js": "^5.1.1", - "browserify-rsa": "^4.0.1", - "create-hash": "^1.2.0", - "create-hmac": "^1.1.7", - "elliptic": "^6.5.3", - "inherits": "^2.0.4", - "parse-asn1": "^5.1.5", - "readable-stream": "^3.6.0", - "safe-buffer": "^5.2.0" - }, - "dependencies": { - "readable-stream": { - "version": "3.6.0", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } - } - }, - "browserify-zlib": { - "version": "0.2.0", - "dev": true, - "requires": { - "pako": "~1.0.5" - } - }, - "browserslist": { - "version": "4.21.4", - "dev": true, - "requires": { - "caniuse-lite": "^1.0.30001400", - "electron-to-chromium": "^1.4.251", - "node-releases": "^2.0.6", - "update-browserslist-db": "^1.0.9" - } - }, - "buffer": { - "version": "6.0.3", - "requires": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, - "buffer-from": { - "version": "1.1.2", - "dev": true - }, - "buffer-xor": { - "version": "1.0.3", - "dev": true - }, - "builtin-modules": { - "version": "1.1.1", - "dev": true - }, - "builtin-status-codes": { - "version": "3.0.0", - "dev": true - }, - "bytes": { - "version": "3.1.2" - }, - "c-kzg": { - "version": "2.0.4", - "requires": { - "bindings": "^1.5.0", - "node-addon-api": "^5.0.0" - }, - "dependencies": { - "node-addon-api": { - "version": "5.1.0" - } - } - }, - "c8": { - "version": "7.12.0", - "dev": true, - "requires": { - "@bcoe/v8-coverage": "^0.2.3", - "@istanbuljs/schema": "^0.1.3", - "find-up": "^5.0.0", - "foreground-child": "^2.0.0", - "istanbul-lib-coverage": "^3.2.0", - "istanbul-lib-report": "^3.0.0", - "istanbul-reports": "^3.1.4", - "rimraf": "^3.0.2", - "test-exclude": "^6.0.0", - "v8-to-istanbul": "^9.0.0", - "yargs": "^16.2.0", - "yargs-parser": "^20.2.9" - } - }, - "cached-path-relative": { - "version": "1.1.0", - "dev": true - }, - "caching-transform": { - "version": "4.0.0", - "dev": true, - "requires": { - "hasha": "^5.0.0", - "make-dir": "^3.0.0", - "package-hash": "^4.0.0", - "write-file-atomic": "^3.0.0" - }, - "dependencies": { - "make-dir": { - "version": "3.1.0", - "dev": true, - "requires": { - "semver": "^6.0.0" - } - }, - "semver": { - "version": "6.3.0", - "dev": true - } - } - }, - "call-bind": { - "version": "1.0.2", - "requires": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - } - }, - "caller-path": { - "version": "0.1.0", - "dev": true, - "requires": { - "callsites": "^0.2.0" - }, - "dependencies": { - "callsites": { - "version": "0.2.0", - "dev": true - } - } - }, - "callsites": { - "version": "3.1.0", - "dev": true - }, - "camel-case": { - "version": "3.0.0", - "dev": true, - "requires": { - "no-case": "^2.2.0", - "upper-case": "^1.1.1" - } - }, - "camelcase": { - "version": "5.3.1", - "dev": true - }, - "caniuse-lite": { - "version": "1.0.30001423", - "dev": true - }, - "caseless": { - "version": "0.12.0" - }, - "catering": { - "version": "2.1.1" - }, - "chai": { - "version": "4.3.6", - "requires": { - "assertion-error": "^1.1.0", - "check-error": "^1.0.2", - "deep-eql": "^3.0.1", - "get-func-name": "^2.0.0", - "loupe": "^2.3.1", - "pathval": "^1.1.1", - "type-detect": "^4.0.5" - } - }, - "chai-checkmark": { - "version": "1.0.1" - }, - "chalk": { - "version": "4.1.2", - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "check-error": { - "version": "1.0.2" - }, - "chokidar": { - "version": "3.5.3", - "dev": true, - "requires": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "fsevents": "~2.3.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "dependencies": { - "glob-parent": { - "version": "5.1.2", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - } - } - }, - "chrome-trace-event": { - "version": "1.0.3", - "dev": true - }, - "cids": { - "version": "1.1.9", - "requires": { - "multibase": "^4.0.1", - "multicodec": "^3.0.1", - "multihashes": "^4.0.1", - "uint8arrays": "^3.0.0" - }, - "dependencies": { - "multicodec": { - "version": "3.2.1", - "requires": { - "uint8arrays": "^3.0.0", - "varint": "^6.0.0" - } - } - } - }, - "cipher-base": { - "version": "1.0.4", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "circular-json": { - "version": "0.3.3", - "dev": true - }, - "class-is": { - "version": "1.1.0" - }, - "classic-level": { - "version": "1.2.0", - "requires": { - "abstract-level": "^1.0.2", - "catering": "^2.1.0", - "module-error": "^1.0.1", - "napi-macros": "~2.0.0", - "node-gyp-build": "^4.3.0" - } - }, - "clean-stack": { - "version": "2.2.0" - }, - "cli-cursor": { - "version": "3.1.0", - "dev": true, - "requires": { - "restore-cursor": "^3.1.0" - } - }, - "cli-truncate": { - "version": "3.1.0", - "dev": true, - "requires": { - "slice-ansi": "^5.0.0", - "string-width": "^5.0.0" - } - }, - "cli-width": { - "version": "2.2.1", - "dev": true - }, - "cliui": { - "version": "7.0.4", - "dev": true, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - }, - "dependencies": { - "emoji-regex": { - "version": "8.0.0", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "dev": true - }, - "string-width": { - "version": "4.2.3", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - } - } - }, - "clone": { - "version": "1.0.4", - "dev": true - }, - "clone-deep": { - "version": "4.0.1", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4", - "kind-of": "^6.0.2", - "shallow-clone": "^3.0.0" - } - }, - "co": { - "version": "4.6.0", - "dev": true - }, - "code-point-at": { - "version": "1.1.0", - "dev": true - }, - "color": { - "version": "3.2.1", - "requires": { - "color-convert": "^1.9.3", - "color-string": "^1.6.0" - }, - "dependencies": { - "color-convert": { - "version": "1.9.3", - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3" - } - } - }, - "color-convert": { - "version": "2.0.1", - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4" - }, - "color-string": { - "version": "1.9.1", - "requires": { - "color-name": "^1.0.0", - "simple-swizzle": "^0.2.2" - } - }, - "colorette": { - "version": "2.0.19", - "dev": true - }, - "colors": { - "version": "0.6.2", - "dev": true - }, - "colorspace": { - "version": "1.1.4", - "requires": { - "color": "^3.1.3", - "text-hex": "1.0.x" - } - }, - "combine-source-map": { - "version": "0.8.0", - "dev": true, - "requires": { - "convert-source-map": "~1.1.0", - "inline-source-map": "~0.6.0", - "lodash.memoize": "~3.0.3", - "source-map": "~0.5.3" - } - }, - "combined-stream": { - "version": "1.0.8", - "requires": { - "delayed-stream": "~1.0.0" - } - }, - "command-exists": { - "version": "1.2.9", - "dev": true - }, - "commander": { - "version": "2.1.0", - "dev": true - }, - "commondir": { - "version": "1.0.1", - "dev": true - }, - "component-emitter": { - "version": "1.3.0", - "dev": true - }, - "concat-map": { - "version": "0.0.1" - }, - "concat-stream": { - "version": "1.6.2", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" - } - }, - "connect": { - "version": "3.7.0", - "requires": { - "debug": "2.6.9", - "finalhandler": "1.1.2", - "parseurl": "~1.3.3", - "utils-merge": "1.0.1" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0" - } - } - }, - "console-browserify": { - "version": "1.2.0", - "dev": true - }, - "constants-browserify": { - "version": "1.0.0", - "dev": true - }, - "contains-path": { - "version": "0.1.0", - "dev": true - }, - "content-type": { - "version": "1.0.4" - }, - "convert-source-map": { - "version": "1.1.3", - "dev": true - }, - "cookie": { - "version": "0.4.2", - "dev": true - }, - "cookiejar": { - "version": "2.1.3", - "dev": true - }, - "core-js": { - "version": "2.6.12", - "dev": true - }, - "core-js-compat": { - "version": "3.25.5", - "dev": true, - "requires": { - "browserslist": "^4.21.4" - } - }, - "core-js-pure": { - "version": "3.25.5", - "dev": true - }, - "core-util-is": { - "version": "1.0.3", - "dev": true - }, - "cors": { - "version": "2.8.5", - "requires": { - "object-assign": "^4", - "vary": "^1" - } - }, - "crc-32": { - "version": "1.2.2" - }, - "create-ecdh": { - "version": "4.0.4", - "dev": true, - "requires": { - "bn.js": "^4.1.0", - "elliptic": "^6.5.3" - }, - "dependencies": { - "bn.js": { - "version": "4.12.0", - "dev": true - } - } - }, - "create-hash": { - "version": "1.2.0", - "dev": true, - "requires": { - "cipher-base": "^1.0.1", - "inherits": "^2.0.1", - "md5.js": "^1.3.4", - "ripemd160": "^2.0.1", - "sha.js": "^2.4.0" - } - }, - "create-hmac": { - "version": "1.1.7", - "dev": true, - "requires": { - "cipher-base": "^1.0.3", - "create-hash": "^1.1.0", - "inherits": "^2.0.1", - "ripemd160": "^2.0.0", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - } - }, - "create-require": { - "version": "1.1.1", - "dev": true - }, - "cross-spawn": { - "version": "7.0.3", - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "dependencies": { - "which": { - "version": "2.0.2", - "requires": { - "isexe": "^2.0.0" - } - } - } - }, - "crypto-browserify": { - "version": "3.12.0", - "dev": true, - "requires": { - "browserify-cipher": "^1.0.0", - "browserify-sign": "^4.0.0", - "create-ecdh": "^4.0.0", - "create-hash": "^1.1.0", - "create-hmac": "^1.1.0", - "diffie-hellman": "^5.0.0", - "inherits": "^2.0.1", - "pbkdf2": "^3.0.3", - "public-encrypt": "^4.0.0", - "randombytes": "^2.0.0", - "randomfill": "^1.0.3" - } - }, - "custom-event": { - "version": "1.0.1", - "dev": true - }, - "d": { - "version": "1.0.1", - "dev": true, - "requires": { - "es5-ext": "^0.10.50", - "type": "^1.0.1" - } - }, - "d3-array": { - "version": "2.12.1", - "dev": true, - "requires": { - "internmap": "^1.0.0" - } - }, - "d3-color": { - "version": "2.0.0", - "dev": true - }, - "d3-dispatch": { - "version": "1.0.6", - "dev": true - }, - "d3-drag": { - "version": "1.2.5", - "dev": true, - "requires": { - "d3-dispatch": "1", - "d3-selection": "1" - } - }, - "d3-ease": { - "version": "1.0.7", - "dev": true - }, - "d3-fg": { - "version": "6.14.0", - "dev": true, - "requires": { - "d3-array": "^2.2.0", - "d3-dispatch": "^1.0.5", - "d3-ease": "^1.0.5", - "d3-hierarchy": "^1.1.8", - "d3-scale": "^3.0.0", - "d3-selection": "^1.4.0", - "d3-zoom": "^1.7.3", - "escape-string-regexp": "^1.0.5", - "hsl-to-rgb-for-reals": "^1.1.0" - } - }, - "d3-format": { - "version": "2.0.0", - "dev": true - }, - "d3-hierarchy": { - "version": "1.1.9", - "dev": true - }, - "d3-interpolate": { - "version": "2.0.1", - "dev": true, - "requires": { - "d3-color": "1 - 2" - } - }, - "d3-scale": { - "version": "3.3.0", - "dev": true, - "requires": { - "d3-array": "^2.3.0", - "d3-format": "1 - 2", - "d3-interpolate": "1.2.0 - 2", - "d3-time": "^2.1.1", - "d3-time-format": "2 - 3" - } - }, - "d3-selection": { - "version": "1.4.2", - "dev": true - }, - "d3-time": { - "version": "2.1.1", - "dev": true, - "requires": { - "d3-array": "2" - } - }, - "d3-time-format": { - "version": "3.0.0", - "dev": true, - "requires": { - "d3-time": "1 - 2" - } - }, - "d3-timer": { - "version": "1.0.10", - "dev": true - }, - "d3-transition": { - "version": "1.3.2", - "dev": true, - "requires": { - "d3-color": "1", - "d3-dispatch": "1", - "d3-ease": "1", - "d3-interpolate": "1", - "d3-selection": "^1.1.0", - "d3-timer": "1" - }, - "dependencies": { - "d3-color": { - "version": "1.4.1", - "dev": true - }, - "d3-interpolate": { - "version": "1.4.0", - "dev": true, - "requires": { - "d3-color": "1" - } - } - } - }, - "d3-zoom": { - "version": "1.8.3", - "dev": true, - "requires": { - "d3-dispatch": "1", - "d3-drag": "1", - "d3-interpolate": "1", - "d3-selection": "1", - "d3-transition": "1" - }, - "dependencies": { - "d3-color": { - "version": "1.4.1", - "dev": true - }, - "d3-interpolate": { - "version": "1.4.0", - "dev": true, - "requires": { - "d3-color": "1" - } - } - } - }, - "damerau-levenshtein": { - "version": "1.0.8", - "dev": true - }, - "dash-ast": { - "version": "1.0.0", - "dev": true - }, - "dashdash": { - "version": "1.14.1", - "requires": { - "assert-plus": "^1.0.0" - } - }, - "date-format": { - "version": "4.0.14", - "dev": true - }, - "debounce": { - "version": "1.2.1", - "dev": true - }, - "debug": { - "version": "4.3.4", - "requires": { - "ms": "2.1.2" - }, - "dependencies": { - "ms": { - "version": "2.1.2" - } - } - }, - "debug-log": { - "version": "1.0.1", - "dev": true - }, - "decamelize": { - "version": "1.2.0", - "dev": true - }, - "deep-eql": { - "version": "3.0.1", - "requires": { - "type-detect": "^4.0.0" - } - }, - "deep-equal": { - "version": "2.0.5", - "dev": true, - "requires": { - "call-bind": "^1.0.0", - "es-get-iterator": "^1.1.1", - "get-intrinsic": "^1.0.1", - "is-arguments": "^1.0.4", - "is-date-object": "^1.0.2", - "is-regex": "^1.1.1", - "isarray": "^2.0.5", - "object-is": "^1.1.4", - "object-keys": "^1.1.1", - "object.assign": "^4.1.2", - "regexp.prototype.flags": "^1.3.0", - "side-channel": "^1.0.3", - "which-boxed-primitive": "^1.0.1", - "which-collection": "^1.0.1", - "which-typed-array": "^1.1.2" - }, - "dependencies": { - "isarray": { - "version": "2.0.5", - "dev": true - } - } - }, - "deep-is": { - "version": "0.1.4", - "dev": true - }, - "default-gateway": { - "version": "6.0.3", - "requires": { - "execa": "^5.0.0" - } - }, - "default-require-extensions": { - "version": "3.0.1", - "dev": true, - "requires": { - "strip-bom": "^4.0.0" - } - }, - "defaults": { - "version": "1.0.4", - "dev": true, - "requires": { - "clone": "^1.0.2" - } - }, - "deferred-leveldown": { - "version": "7.0.0", - "dev": true, - "requires": { - "abstract-leveldown": "^7.2.0", - "inherits": "^2.0.3" - } - }, - "define-properties": { - "version": "1.1.4", - "requires": { - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - } - }, - "defined": { - "version": "1.0.1", - "dev": true - }, - "deglob": { - "version": "2.1.1", - "dev": true, - "requires": { - "find-root": "^1.0.0", - "glob": "^7.0.5", - "ignore": "^3.0.9", - "pkg-config": "^1.1.0", - "run-parallel": "^1.1.2", - "uniq": "^1.0.1" - }, - "dependencies": { - "ignore": { - "version": "3.3.10", - "dev": true - } - } - }, - "delay": { - "version": "5.0.0" - }, - "delayed-stream": { - "version": "1.0.0" - }, - "depd": { - "version": "2.0.0" - }, - "deps-sort": { - "version": "2.0.1", - "dev": true, - "requires": { - "JSONStream": "^1.0.3", - "shasum-object": "^1.0.0", - "subarg": "^1.0.0", - "through2": "^2.0.0" - } - }, - "des.js": { - "version": "1.0.1", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0" - } - }, - "destroy": { - "version": "1.2.0" - }, - "detect-indent": { - "version": "6.1.0", - "dev": true - }, - "detect-newline": { - "version": "3.1.0", - "dev": true - }, - "detect-node": { - "version": "2.1.0" - }, - "detective": { - "version": "5.2.1", - "dev": true, - "requires": { - "acorn-node": "^1.8.2", - "defined": "^1.0.0", - "minimist": "^1.2.6" - } - }, - "dezalgo": { - "version": "1.0.3", - "dev": true, - "requires": { - "asap": "^2.0.0", - "wrappy": "1" - } - }, - "di": { - "version": "0.0.1", - "dev": true - }, - "diff": { - "version": "4.0.2" - }, - "diffie-hellman": { - "version": "5.0.3", - "dev": true, - "requires": { - "bn.js": "^4.1.0", - "miller-rabin": "^4.0.0", - "randombytes": "^2.0.0" - }, - "dependencies": { - "bn.js": { - "version": "4.12.0", - "dev": true - } - } - }, - "dir-glob": { - "version": "3.0.1", - "dev": true, - "requires": { - "path-type": "^4.0.0" - } - }, - "dirty-chai": { - "version": "2.0.1", - "requires": {} - }, - "dns-over-http-resolver": { - "version": "1.2.3", - "requires": { - "debug": "^4.3.1", - "native-fetch": "^3.0.0", - "receptacle": "^1.3.2" - } - }, - "doctrine": { - "version": "3.0.0", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - }, - "dom-serialize": { - "version": "2.2.1", - "dev": true, - "requires": { - "custom-event": "~1.0.0", - "ent": "~2.2.0", - "extend": "^3.0.0", - "void-elements": "^2.0.0" - } - }, - "domain-browser": { - "version": "1.2.0", - "dev": true - }, - "dotignore": { - "version": "0.1.2", - "dev": true, - "requires": { - "minimatch": "^3.0.4" - } - }, - "duplexer2": { - "version": "0.1.4", - "dev": true, - "requires": { - "readable-stream": "^2.0.2" - } - }, - "duplexify": { - "version": "3.7.1", - "dev": true, - "requires": { - "end-of-stream": "^1.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.0.0", - "stream-shift": "^1.0.0" - } - }, - "eastasianwidth": { - "version": "0.2.0", - "dev": true - }, - "ecc-jsbn": { - "version": "0.1.2", - "requires": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - }, - "dependencies": { - "jsbn": { - "version": "0.1.1" - } - } - }, - "ee-first": { - "version": "1.1.1" - }, - "electron-fetch": { - "version": "1.9.1", - "requires": { - "encoding": "^0.1.13" - } - }, - "electron-to-chromium": { - "version": "1.4.284", - "dev": true - }, - "elliptic": { - "version": "6.5.4", - "requires": { - "bn.js": "^4.11.9", - "brorand": "^1.1.0", - "hash.js": "^1.0.0", - "hmac-drbg": "^1.0.1", - "inherits": "^2.0.4", - "minimalistic-assert": "^1.0.1", - "minimalistic-crypto-utils": "^1.0.1" - }, - "dependencies": { - "bn.js": { - "version": "4.12.0" - } - } - }, - "emoji-regex": { - "version": "9.2.2", - "dev": true - }, - "emojis-list": { - "version": "3.0.0", - "dev": true - }, - "enabled": { - "version": "2.0.0" - }, - "encodeurl": { - "version": "1.0.2" - }, - "encoding": { - "version": "0.1.13", - "requires": { - "iconv-lite": "^0.6.2" - }, - "dependencies": { - "iconv-lite": { - "version": "0.6.3", - "requires": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - } - } - } - }, - "encoding-down": { - "version": "7.1.0", - "dev": true, - "requires": { - "abstract-leveldown": "^7.2.0", - "inherits": "^2.0.3", - "level-codec": "^10.0.0", - "level-errors": "^3.0.0" - } - }, - "end-of-stream": { - "version": "1.4.4", - "dev": true, - "requires": { - "once": "^1.4.0" - } - }, - "engine.io": { - "version": "6.2.0", - "dev": true, - "requires": { - "@types/cookie": "^0.4.1", - "@types/cors": "^2.8.12", - "@types/node": ">=10.0.0", - "accepts": "~1.3.4", - "base64id": "2.0.0", - "cookie": "~0.4.1", - "cors": "~2.8.5", - "debug": "~4.3.1", - "engine.io-parser": "~5.0.3", - "ws": "~8.2.3" - }, - "dependencies": { - "ws": { - "version": "8.2.3", - "dev": true, - "requires": {} - } - } - }, - "engine.io-parser": { - "version": "5.0.4", - "dev": true - }, - "enhanced-resolve": { - "version": "5.10.0", - "dev": true, - "requires": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - } - }, - "ent": { - "version": "2.2.0", - "dev": true - }, - "env-string": { - "version": "1.0.1", - "dev": true - }, - "envinfo": { - "version": "7.8.1", - "dev": true - }, - "err-code": { - "version": "2.0.3" - }, - "error-ex": { - "version": "1.3.2", - "dev": true, - "requires": { - "is-arrayish": "^0.2.1" - } - }, - "es-abstract": { - "version": "1.20.4", - "requires": { - "call-bind": "^1.0.2", - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "function.prototype.name": "^1.1.5", - "get-intrinsic": "^1.1.3", - "get-symbol-description": "^1.0.0", - "has": "^1.0.3", - "has-property-descriptors": "^1.0.0", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.3", - "is-callable": "^1.2.7", - "is-negative-zero": "^2.0.2", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", - "is-string": "^1.0.7", - "is-weakref": "^1.0.2", - "object-inspect": "^1.12.2", - "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.4.3", - "safe-regex-test": "^1.0.0", - "string.prototype.trimend": "^1.0.5", - "string.prototype.trimstart": "^1.0.5", - "unbox-primitive": "^1.0.2" - } - }, - "es-get-iterator": { - "version": "1.1.2", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.0", - "has-symbols": "^1.0.1", - "is-arguments": "^1.1.0", - "is-map": "^2.0.2", - "is-set": "^2.0.2", - "is-string": "^1.0.5", - "isarray": "^2.0.5" - }, - "dependencies": { - "isarray": { - "version": "2.0.5", - "dev": true - } - } - }, - "es-module-lexer": { - "version": "0.9.3", - "dev": true - }, - "es-shim-unscopables": { - "version": "1.0.0", - "dev": true, - "requires": { - "has": "^1.0.3" - } - }, - "es-to-primitive": { - "version": "1.2.1", - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - } - }, - "es5-ext": { - "version": "0.10.62", - "dev": true, - "requires": { - "es6-iterator": "^2.0.3", - "es6-symbol": "^3.1.3", - "next-tick": "^1.1.0" - } - }, - "es6-error": { - "version": "4.1.1", - "dev": true - }, - "es6-iterator": { - "version": "2.0.3", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "^0.10.35", - "es6-symbol": "^3.1.1" - } - }, - "es6-map": { - "version": "0.1.5", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "~0.10.14", - "es6-iterator": "~2.0.1", - "es6-set": "~0.1.5", - "es6-symbol": "~3.1.1", - "event-emitter": "~0.3.5" - } - }, - "es6-object-assign": { - "version": "1.1.0", - "dev": true - }, - "es6-promise": { - "version": "4.2.8" - }, - "es6-promisify": { - "version": "5.0.0", - "requires": { - "es6-promise": "^4.0.3" - } - }, - "es6-set": { - "version": "0.1.6", - "dev": true, - "requires": { - "d": "^1.0.1", - "es5-ext": "^0.10.62", - "es6-iterator": "~2.0.3", - "es6-symbol": "^3.1.3", - "event-emitter": "^0.3.5", - "type": "^2.7.2" - }, - "dependencies": { - "type": { - "version": "2.7.2", - "dev": true - } - } - }, - "es6-symbol": { - "version": "3.1.3", - "dev": true, - "requires": { - "d": "^1.0.1", - "ext": "^1.1.2" - } - }, - "es6-weak-map": { - "version": "2.0.3", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "^0.10.46", - "es6-iterator": "^2.0.3", - "es6-symbol": "^3.1.1" - } - }, - "escalade": { - "version": "3.1.1" - }, - "escape-html": { - "version": "1.0.3" - }, - "escape-string-regexp": { - "version": "1.0.5", - "dev": true - }, - "escope": { - "version": "3.6.0", - "dev": true, - "requires": { - "es6-map": "^0.1.3", - "es6-weak-map": "^2.0.1", - "esrecurse": "^4.1.0", - "estraverse": "^4.1.1" - } - }, - "eslint": { - "version": "8.22.0", - "dev": true, - "requires": { - "@eslint/eslintrc": "^1.3.0", - "@humanwhocodes/config-array": "^0.10.4", - "@humanwhocodes/gitignore-to-minimatch": "^1.0.2", - "ajv": "^6.10.0", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.1.1", - "eslint-utils": "^3.0.0", - "eslint-visitor-keys": "^3.3.0", - "espree": "^9.3.3", - "esquery": "^1.4.0", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "find-up": "^5.0.0", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^6.0.1", - "globals": "^13.15.0", - "globby": "^11.1.0", - "grapheme-splitter": "^1.0.4", - "ignore": "^5.2.0", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "regexpp": "^3.2.0", - "strip-ansi": "^6.0.1", - "strip-json-comments": "^3.1.0", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" - }, - "dependencies": { - "escape-string-regexp": { - "version": "4.0.0", - "dev": true - }, - "eslint-scope": { - "version": "7.1.1", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - } - }, - "estraverse": { - "version": "5.3.0", - "dev": true - } - } - }, - "eslint-config-prettier": { - "version": "8.5.0", - "dev": true, - "requires": {} - }, - "eslint-config-standard": { - "version": "10.2.1", - "dev": true, - "requires": {} - }, - "eslint-config-typestrict": { - "version": "1.0.5", - "dev": true, - "requires": {} - }, - "eslint-formatter-codeframe": { - "version": "7.32.1", - "dev": true, - "requires": { - "@babel/code-frame": "7.12.11", - "chalk": "^4.0.0" - } - }, - "eslint-import-resolver-node": { - "version": "0.3.6", - "dev": true, - "requires": { - "debug": "^3.2.7", - "resolve": "^1.20.0" - }, - "dependencies": { - "debug": { - "version": "3.2.7", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "ms": { - "version": "2.1.3", - "dev": true - } - } - }, - "eslint-module-utils": { - "version": "2.7.4", - "dev": true, - "requires": { - "debug": "^3.2.7" - }, - "dependencies": { - "debug": { - "version": "3.2.7", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "ms": { - "version": "2.1.3", - "dev": true - } - } - }, - "eslint-plugin-escompat": { - "version": "3.3.4", - "dev": true, - "requires": { - "browserslist": "^4.21.0" - } - }, - "eslint-plugin-eslint-comments": { - "version": "3.2.0", - "dev": true, - "requires": { - "escape-string-regexp": "^1.0.5", - "ignore": "^5.0.5" - } - }, - "eslint-plugin-ethereumjs": { - "version": "file:eslint" - }, - "eslint-plugin-filenames": { - "version": "1.3.2", - "dev": true, - "requires": { - "lodash.camelcase": "4.3.0", - "lodash.kebabcase": "4.1.1", - "lodash.snakecase": "4.1.1", - "lodash.upperfirst": "4.3.1" - } - }, - "eslint-plugin-github": { - "version": "4.3.7", - "dev": true, - "requires": { - "@typescript-eslint/eslint-plugin": "^5.1.0", - "@typescript-eslint/parser": "^5.1.0", - "eslint-config-prettier": ">=8.0.0", - "eslint-plugin-escompat": "^3.1.0", - "eslint-plugin-eslint-comments": "^3.2.0", - "eslint-plugin-filenames": "^1.3.2", - "eslint-plugin-i18n-text": "^1.0.1", - "eslint-plugin-import": "^2.25.2", - "eslint-plugin-jsx-a11y": "^6.6.0", - "eslint-plugin-no-only-tests": "^2.6.0", - "eslint-plugin-prettier": "^4.0.0", - "eslint-rule-documentation": ">=1.0.0", - "jsx-ast-utils": "^3.3.2", - "prettier": "^2.2.1", - "svg-element-attributes": "^1.3.1" - } - }, - "eslint-plugin-i18n-text": { - "version": "1.0.1", - "dev": true, - "requires": {} - }, - "eslint-plugin-implicit-dependencies": { - "version": "1.1.1", - "dev": true, - "requires": { - "builtin-modules": "^1.1.1", - "findup": "^0.1.5" - } - }, - "eslint-plugin-import": { - "version": "2.26.0", - "dev": true, - "requires": { - "array-includes": "^3.1.4", - "array.prototype.flat": "^1.2.5", - "debug": "^2.6.9", - "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.6", - "eslint-module-utils": "^2.7.3", - "has": "^1.0.3", - "is-core-module": "^2.8.1", - "is-glob": "^4.0.3", - "minimatch": "^3.1.2", - "object.values": "^1.1.5", - "resolve": "^1.22.0", - "tsconfig-paths": "^3.14.1" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "doctrine": { - "version": "2.1.0", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - }, - "ms": { - "version": "2.0.0", - "dev": true - } - } - }, - "eslint-plugin-jsx-a11y": { - "version": "6.6.1", - "dev": true, - "requires": { - "@babel/runtime": "^7.18.9", - "aria-query": "^4.2.2", - "array-includes": "^3.1.5", - "ast-types-flow": "^0.0.7", - "axe-core": "^4.4.3", - "axobject-query": "^2.2.0", - "damerau-levenshtein": "^1.0.8", - "emoji-regex": "^9.2.2", - "has": "^1.0.3", - "jsx-ast-utils": "^3.3.2", - "language-tags": "^1.0.5", - "minimatch": "^3.1.2", - "semver": "^6.3.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "dev": true - } - } - }, - "eslint-plugin-no-only-tests": { - "version": "2.6.0", - "dev": true - }, - "eslint-plugin-node": { - "version": "4.2.3", - "dev": true, - "requires": { - "ignore": "^3.0.11", - "minimatch": "^3.0.2", - "object-assign": "^4.0.1", - "resolve": "^1.1.7", - "semver": "5.3.0" - }, - "dependencies": { - "ignore": { - "version": "3.3.10", - "dev": true - }, - "semver": { - "version": "5.3.0", - "dev": true - } - } - }, - "eslint-plugin-prettier": { - "version": "4.2.1", - "dev": true, - "requires": { - "prettier-linter-helpers": "^1.0.0" - } - }, - "eslint-plugin-promise": { - "version": "3.5.0", - "dev": true - }, - "eslint-plugin-simple-import-sort": { - "version": "7.0.0", - "dev": true, - "requires": {} - }, - "eslint-plugin-sonarjs": { - "version": "0.14.0", - "dev": true, - "requires": {} - }, - "eslint-plugin-standard": { - "version": "3.0.1", - "dev": true, - "requires": {} - }, - "eslint-rule-documentation": { - "version": "1.0.23", - "dev": true - }, - "eslint-scope": { - "version": "5.1.1", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - } - }, - "eslint-utils": { - "version": "3.0.0", - "dev": true, - "requires": { - "eslint-visitor-keys": "^2.0.0" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "2.1.0", - "dev": true - } - } - }, - "eslint-visitor-keys": { - "version": "3.3.0", - "dev": true - }, - "espree": { - "version": "9.4.0", - "dev": true, - "requires": { - "acorn": "^8.8.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.3.0" - } - }, - "esprima": { - "version": "4.0.1", - "dev": true - }, - "esquery": { - "version": "1.4.0", - "dev": true, - "requires": { - "estraverse": "^5.1.0" - }, - "dependencies": { - "estraverse": { - "version": "5.3.0", - "dev": true - } - } - }, - "esrecurse": { - "version": "4.3.0", - "dev": true, - "requires": { - "estraverse": "^5.2.0" - }, - "dependencies": { - "estraverse": { - "version": "5.3.0", - "dev": true - } - } - }, - "estraverse": { - "version": "4.3.0", - "dev": true - }, - "estree-is-member-expression": { - "version": "1.0.0", - "dev": true - }, - "esutils": { - "version": "2.0.3", - "dev": true - }, - "ethereum-cryptography": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-2.0.0.tgz", - "integrity": "sha512-g25m4EtfQGjstWgVE1aIz7XYYjf3kH5kG17ULWVB5dH6uLahsoltOhACzSxyDV+fhn4gbR4xRrOXGe6r2uh4Bg==", - "requires": { - "@noble/curves": "1.0.0", - "@noble/hashes": "1.3.0", - "@scure/bip32": "1.3.0", - "@scure/bip39": "1.2.0" - } - }, - "ethers": { - "version": "5.7.2", - "requires": { - "@ethersproject/abi": "5.7.0", - "@ethersproject/abstract-provider": "5.7.0", - "@ethersproject/abstract-signer": "5.7.0", - "@ethersproject/address": "5.7.0", - "@ethersproject/base64": "5.7.0", - "@ethersproject/basex": "5.7.0", - "@ethersproject/bignumber": "5.7.0", - "@ethersproject/bytes": "5.7.0", - "@ethersproject/constants": "5.7.0", - "@ethersproject/contracts": "5.7.0", - "@ethersproject/hash": "5.7.0", - "@ethersproject/hdnode": "5.7.0", - "@ethersproject/json-wallets": "5.7.0", - "@ethersproject/keccak256": "5.7.0", - "@ethersproject/logger": "5.7.0", - "@ethersproject/networks": "5.7.1", - "@ethersproject/pbkdf2": "5.7.0", - "@ethersproject/properties": "5.7.0", - "@ethersproject/providers": "5.7.2", - "@ethersproject/random": "5.7.0", - "@ethersproject/rlp": "5.7.0", - "@ethersproject/sha2": "5.7.0", - "@ethersproject/signing-key": "5.7.0", - "@ethersproject/solidity": "5.7.0", - "@ethersproject/strings": "5.7.0", - "@ethersproject/transactions": "5.7.0", - "@ethersproject/units": "5.7.0", - "@ethersproject/wallet": "5.7.0", - "@ethersproject/web": "5.7.1", - "@ethersproject/wordlists": "5.7.0" - } - }, - "event-emitter": { - "version": "0.3.5", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "~0.10.14" - } - }, - "event-iterator": { - "version": "2.0.0" - }, - "event-target-shim": { - "version": "5.0.1" - }, - "eventemitter3": { - "version": "4.0.7" - }, - "events": { - "version": "2.1.0", - "dev": true - }, - "evp_bytestokey": { - "version": "1.0.3", - "dev": true, - "requires": { - "md5.js": "^1.3.4", - "safe-buffer": "^5.1.1" - } - }, - "execa": { - "version": "5.1.1", - "requires": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - } - }, - "execspawn": { - "version": "1.0.1", - "dev": true, - "requires": { - "util-extend": "^1.0.1" - } - }, - "exit-hook": { - "version": "1.1.1", - "dev": true - }, - "ext": { - "version": "1.7.0", - "dev": true, - "requires": { - "type": "^2.7.2" - }, - "dependencies": { - "type": { - "version": "2.7.2", - "dev": true - } - } - }, - "extend": { - "version": "3.0.2" - }, - "extsprintf": { - "version": "1.3.0" - }, - "eyes": { - "version": "0.1.8" - }, - "fast-deep-equal": { - "version": "3.1.3" - }, - "fast-diff": { - "version": "1.2.0", - "dev": true - }, - "fast-fifo": { - "version": "1.1.0" - }, - "fast-glob": { - "version": "3.2.12", - "dev": true, - "requires": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "dependencies": { - "glob-parent": { - "version": "5.1.2", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - } - } - }, - "fast-json-stable-stringify": { - "version": "2.1.0" - }, - "fast-levenshtein": { - "version": "2.0.6", - "dev": true - }, - "fast-redact": { - "version": "2.1.0", - "dev": true - }, - "fast-safe-stringify": { - "version": "2.1.1", - "dev": true - }, - "fastest-levenshtein": { - "version": "1.0.16", - "dev": true - }, - "fastq": { - "version": "1.13.0", - "dev": true, - "requires": { - "reusify": "^1.0.4" - } - }, - "fecha": { - "version": "4.2.3" - }, - "figures": { - "version": "1.7.0", - "dev": true, - "requires": { - "escape-string-regexp": "^1.0.5", - "object-assign": "^4.1.0" - } - }, - "file-entry-cache": { - "version": "6.0.1", - "dev": true, - "requires": { - "flat-cache": "^3.0.4" - } - }, - "file-replace-loader": { - "version": "1.4.0", - "dev": true, - "requires": { - "loader-utils": "^2.0.0", - "schema-utils": "^2.7.1" - } - }, - "file-stream-rotator": { - "version": "0.6.1", - "requires": { - "moment": "^2.29.1" - } - }, - "file-uri-to-path": { - "version": "1.0.0" - }, - "fill-range": { - "version": "7.0.1", - "dev": true, - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "finalhandler": { - "version": "1.1.2", - "requires": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "statuses": "~1.5.0", - "unpipe": "~1.0.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0" - }, - "on-finished": { - "version": "2.3.0", - "requires": { - "ee-first": "1.1.1" - } - } - } - }, - "find-cache-dir": { - "version": "3.3.2", - "dev": true, - "requires": { - "commondir": "^1.0.1", - "make-dir": "^3.0.2", - "pkg-dir": "^4.1.0" - }, - "dependencies": { - "make-dir": { - "version": "3.1.0", - "dev": true, - "requires": { - "semver": "^6.0.0" - } - }, - "semver": { - "version": "6.3.0", - "dev": true - } - } - }, - "find-root": { - "version": "1.1.0", - "dev": true - }, - "find-up": { - "version": "5.0.0", - "dev": true, - "requires": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - } - }, - "findup": { - "version": "0.1.5", - "dev": true, - "requires": { - "colors": "~0.6.0-1", - "commander": "~2.1.0" - } - }, - "flat-cache": { - "version": "3.0.4", - "dev": true, - "requires": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" - } - }, - "flatstr": { - "version": "1.0.12", - "dev": true - }, - "flatted": { - "version": "3.2.7", - "dev": true - }, - "fn.name": { - "version": "1.1.0" - }, - "follow-redirects": { - "version": "1.15.2", - "dev": true - }, - "for-each": { - "version": "0.3.3", - "requires": { - "is-callable": "^1.1.3" - } - }, - "foreground-child": { - "version": "2.0.0", - "dev": true, - "requires": { - "cross-spawn": "^7.0.0", - "signal-exit": "^3.0.2" - } - }, - "forever-agent": { - "version": "0.6.1" - }, - "form-data": { - "version": "2.3.3", - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - } - }, - "formidable": { - "version": "2.0.1", - "dev": true, - "requires": { - "dezalgo": "1.0.3", - "hexoid": "1.0.0", - "once": "1.4.0", - "qs": "6.9.3" - }, - "dependencies": { - "qs": { - "version": "6.9.3", - "dev": true - } - } - }, - "fromentries": { - "version": "1.3.2", - "dev": true - }, - "fs-extra": { - "version": "10.1.0", - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - } - }, - "fs.realpath": { - "version": "1.0.0", - "dev": true - }, - "function-bind": { - "version": "1.1.1" - }, - "function.prototype.name": { - "version": "1.1.5", - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.0", - "functions-have-names": "^1.2.2" - } - }, - "functional-red-black-tree": { - "version": "1.0.1" - }, - "functions-have-names": { - "version": "1.2.3" - }, - "generate-function": { - "version": "2.3.1", - "dev": true, - "requires": { - "is-property": "^1.0.2" - } - }, - "generate-object-property": { - "version": "1.2.0", - "dev": true, - "requires": { - "is-property": "^1.0.0" - } - }, - "gensync": { - "version": "1.0.0-beta.2", - "dev": true - }, - "get-assigned-identifiers": { - "version": "1.2.0", - "dev": true - }, - "get-caller-file": { - "version": "2.0.5" - }, - "get-func-name": { - "version": "2.0.0" - }, - "get-intrinsic": { - "version": "1.1.3", - "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.3" - } - }, - "get-iterator": { - "version": "1.0.2" - }, - "get-package-type": { - "version": "0.1.0", - "dev": true - }, - "get-stdin": { - "version": "5.0.1", - "dev": true - }, - "get-stream": { - "version": "6.0.1" - }, - "get-symbol-description": { - "version": "1.0.0", - "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" - } - }, - "getpass": { - "version": "0.1.7", - "requires": { - "assert-plus": "^1.0.0" - } - }, - "git-hooks-list": { - "version": "1.0.3", - "dev": true - }, - "glob": { - "version": "7.2.3", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "glob-parent": { - "version": "6.0.2", - "dev": true, - "requires": { - "is-glob": "^4.0.3" - } - }, - "glob-to-regexp": { - "version": "0.4.1", - "dev": true - }, - "globals": { - "version": "13.17.0", - "dev": true, - "requires": { - "type-fest": "^0.20.2" - } - }, - "globby": { - "version": "11.1.0", - "dev": true, - "requires": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - } - }, - "graceful-fs": { - "version": "4.2.10" - }, - "grapheme-splitter": { - "version": "1.0.4", - "dev": true - }, - "handlebars": { - "version": "4.7.7", - "dev": true, - "requires": { - "minimist": "^1.2.5", - "neo-async": "^2.6.0", - "source-map": "^0.6.1", - "uglify-js": "^3.1.4", - "wordwrap": "^1.0.0" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "dev": true - } - } - }, - "har-schema": { - "version": "2.0.0" - }, - "har-validator": { - "version": "5.1.5", - "requires": { - "ajv": "^6.12.3", - "har-schema": "^2.0.0" - } - }, - "has": { - "version": "1.0.3", - "requires": { - "function-bind": "^1.1.1" - } - }, - "has-ansi": { - "version": "2.0.0", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "dev": true - } - } - }, - "has-bigints": { - "version": "1.0.2" - }, - "has-dynamic-import": { - "version": "2.0.1", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" - } - }, - "has-flag": { - "version": "4.0.0" - }, - "has-property-descriptors": { - "version": "1.0.0", - "requires": { - "get-intrinsic": "^1.1.1" - } - }, - "has-symbols": { - "version": "1.0.3" - }, - "has-tostringtag": { - "version": "1.0.0", - "requires": { - "has-symbols": "^1.0.2" - } - }, - "has-unicode": { - "version": "2.0.1", - "dev": true - }, - "hash-base": { - "version": "3.1.0", - "dev": true, - "requires": { - "inherits": "^2.0.4", - "readable-stream": "^3.6.0", - "safe-buffer": "^5.2.0" - }, - "dependencies": { - "readable-stream": { - "version": "3.6.0", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } - } - }, - "hash.js": { - "version": "1.1.7", - "requires": { - "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.1" - } - }, - "hasha": { - "version": "5.2.2", - "dev": true, - "requires": { - "is-stream": "^2.0.0", - "type-fest": "^0.8.0" - }, - "dependencies": { - "type-fest": { - "version": "0.8.1", - "dev": true - } - } - }, - "hashlru": { - "version": "2.3.0" - }, - "heap": { - "version": "0.2.7" - }, - "hexoid": { - "version": "1.0.0", - "dev": true - }, - "hmac-drbg": { - "version": "1.0.1", - "requires": { - "hash.js": "^1.0.3", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.1" - } - }, - "hsl-to-rgb-for-reals": { - "version": "1.1.1", - "dev": true - }, - "html-escaper": { - "version": "2.0.2", - "dev": true - }, - "htmlescape": { - "version": "1.1.1", - "dev": true - }, - "http-errors": { - "version": "2.0.0", - "requires": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - }, - "dependencies": { - "statuses": { - "version": "2.0.1" - } - } - }, - "http-proxy": { - "version": "1.18.1", - "dev": true, - "requires": { - "eventemitter3": "^4.0.0", - "follow-redirects": "^1.0.0", - "requires-port": "^1.0.0" - } - }, - "http-signature": { - "version": "1.2.0", - "requires": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - } - }, - "https-browserify": { - "version": "1.0.0", - "dev": true - }, - "human-signals": { - "version": "2.1.0" - }, - "hyperscript-attribute-to-property": { - "version": "1.0.2", - "dev": true - }, - "hyperx": { - "version": "2.5.4", - "dev": true, - "requires": { - "hyperscript-attribute-to-property": "^1.0.0" - } - }, - "iconv-lite": { - "version": "0.4.24", - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "ieee754": { - "version": "1.2.1" - }, - "ignore": { - "version": "5.2.0", - "dev": true - }, - "import-fresh": { - "version": "3.3.0", - "dev": true, - "requires": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - } - }, - "import-local": { - "version": "3.1.0", - "dev": true, - "requires": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" - } - }, - "imurmurhash": { - "version": "0.1.4", - "dev": true - }, - "indent-string": { - "version": "4.0.0" - }, - "inflight": { - "version": "1.0.6", - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4" - }, - "inline-source-map": { - "version": "0.6.2", - "dev": true, - "requires": { - "source-map": "~0.5.3" - } - }, - "inquirer": { - "version": "0.12.0", - "dev": true, - "requires": { - "ansi-escapes": "^1.1.0", - "ansi-regex": "^2.0.0", - "chalk": "^1.0.0", - "cli-cursor": "^1.0.1", - "cli-width": "^2.0.0", - "figures": "^1.3.5", - "lodash": "^4.3.0", - "readline2": "^1.0.1", - "run-async": "^0.1.0", - "rx-lite": "^3.1.2", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.0", - "through": "^2.3.6" - }, - "dependencies": { - "ansi-escapes": { - "version": "1.4.0", - "dev": true - }, - "ansi-regex": { - "version": "2.1.1", - "dev": true - }, - "ansi-styles": { - "version": "2.2.1", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } - }, - "cli-cursor": { - "version": "1.0.2", - "dev": true, - "requires": { - "restore-cursor": "^1.0.1" - } - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "onetime": { - "version": "1.1.0", - "dev": true - }, - "restore-cursor": { - "version": "1.0.1", - "dev": true, - "requires": { - "exit-hook": "^1.0.0", - "onetime": "^1.0.0" - } - }, - "string-width": { - "version": "1.0.2", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "supports-color": { - "version": "2.0.0", - "dev": true - } - } - }, - "insert-module-globals": { - "version": "7.2.1", - "dev": true, - "requires": { - "acorn-node": "^1.5.2", - "combine-source-map": "^0.8.0", - "concat-stream": "^1.6.1", - "is-buffer": "^1.1.0", - "JSONStream": "^1.0.3", - "path-is-absolute": "^1.0.1", - "process": "~0.11.0", - "through2": "^2.0.0", - "undeclared-identifiers": "^1.1.2", - "xtend": "^4.0.0" - }, - "dependencies": { - "is-buffer": { - "version": "1.1.6", - "dev": true - } - } - }, - "interface-datastore": { - "version": "3.0.6", - "requires": { - "err-code": "^3.0.1", - "ipfs-utils": "^6.0.0", - "iso-random-stream": "^2.0.0", - "it-all": "^1.0.2", - "it-drain": "^1.0.1", - "nanoid": "^3.0.2" - }, - "dependencies": { - "err-code": { - "version": "3.0.1" - } - } - }, - "internal-slot": { - "version": "1.0.3", - "requires": { - "get-intrinsic": "^1.1.0", - "has": "^1.0.3", - "side-channel": "^1.0.4" - } - }, - "internmap": { - "version": "1.0.1", - "dev": true - }, - "interpret": { - "version": "2.2.0", - "dev": true - }, - "ip-address": { - "version": "6.4.0", - "requires": { - "jsbn": "1.1.0", - "lodash.find": "4.6.0", - "lodash.max": "4.0.1", - "lodash.merge": "4.6.2", - "lodash.padstart": "4.6.1", - "lodash.repeat": "4.1.0", - "sprintf-js": "1.1.2" - } - }, - "ip-regex": { - "version": "4.3.0" - }, - "ipaddr.js": { - "version": "2.0.1" - }, - "ipfs-utils": { - "version": "6.0.8", - "requires": { - "abort-controller": "^3.0.0", - "any-signal": "^2.1.0", - "buffer": "^6.0.1", - "electron-fetch": "^1.7.2", - "err-code": "^3.0.1", - "is-electron": "^2.2.0", - "iso-url": "^1.0.0", - "it-glob": "~0.0.11", - "it-to-stream": "^1.0.0", - "merge-options": "^3.0.4", - "nanoid": "^3.1.20", - "native-abort-controller": "^1.0.3", - "native-fetch": "^3.0.0", - "node-fetch": "^2.6.1", - "stream-to-it": "^0.2.2" - }, - "dependencies": { - "err-code": { - "version": "3.0.1" - } - } - }, - "is-arguments": { - "version": "1.1.1", - "requires": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - } - }, - "is-arrayish": { - "version": "0.2.1", - "dev": true - }, - "is-bigint": { - "version": "1.0.4", - "requires": { - "has-bigints": "^1.0.1" - } - }, - "is-binary-path": { - "version": "2.1.0", - "dev": true, - "requires": { - "binary-extensions": "^2.0.0" - } - }, - "is-boolean-attribute": { - "version": "0.0.1", - "dev": true - }, - "is-boolean-object": { - "version": "1.1.2", - "requires": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - } - }, - "is-buffer": { - "version": "2.0.5" - }, - "is-callable": { - "version": "1.2.7" - }, - "is-core-module": { - "version": "2.11.0", - "dev": true, - "requires": { - "has": "^1.0.3" - } - }, - "is-date-object": { - "version": "1.0.5", - "requires": { - "has-tostringtag": "^1.0.0" - } - }, - "is-docker": { - "version": "2.2.1", - "dev": true - }, - "is-electron": { - "version": "2.2.1" - }, - "is-extglob": { - "version": "2.1.1", - "dev": true - }, - "is-fn": { - "version": "1.0.0" - }, - "is-fullwidth-code-point": { - "version": "4.0.0", - "dev": true - }, - "is-generator-function": { - "version": "1.0.10", - "requires": { - "has-tostringtag": "^1.0.0" - } - }, - "is-glob": { - "version": "4.0.3", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-ip": { - "version": "3.1.0", - "requires": { - "ip-regex": "^4.0.0" - } - }, - "is-loopback-addr": { - "version": "1.0.1" - }, - "is-map": { - "version": "2.0.2", - "dev": true - }, - "is-my-ip-valid": { - "version": "1.0.1", - "dev": true - }, - "is-my-json-valid": { - "version": "2.20.6", - "dev": true, - "requires": { - "generate-function": "^2.0.0", - "generate-object-property": "^1.1.0", - "is-my-ip-valid": "^1.0.0", - "jsonpointer": "^5.0.0", - "xtend": "^4.0.0" - } - }, - "is-nan": { - "version": "1.3.2", - "dev": true, - "requires": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3" - } - }, - "is-negative-zero": { - "version": "2.0.2" - }, - "is-number": { - "version": "7.0.0", - "dev": true - }, - "is-number-object": { - "version": "1.0.7", - "requires": { - "has-tostringtag": "^1.0.0" - } - }, - "is-plain-obj": { - "version": "2.1.0" - }, - "is-plain-object": { - "version": "2.0.4", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - }, - "is-property": { - "version": "1.0.2", - "dev": true - }, - "is-regex": { - "version": "1.1.4", - "requires": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - } - }, - "is-regexp": { - "version": "1.0.0", - "dev": true - }, - "is-resolvable": { - "version": "1.1.0", - "dev": true - }, - "is-set": { - "version": "2.0.2", - "dev": true - }, - "is-shared-array-buffer": { - "version": "1.0.2", - "requires": { - "call-bind": "^1.0.2" - } - }, - "is-stream": { - "version": "2.0.1" - }, - "is-string": { - "version": "1.0.7", - "requires": { - "has-tostringtag": "^1.0.0" - } - }, - "is-symbol": { - "version": "1.0.4", - "requires": { - "has-symbols": "^1.0.2" - } - }, - "is-typed-array": { - "version": "1.1.9", - "requires": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "es-abstract": "^1.20.0", - "for-each": "^0.3.3", - "has-tostringtag": "^1.0.0" - } - }, - "is-typedarray": { - "version": "1.0.0" - }, - "is-weakmap": { - "version": "2.0.1", - "dev": true - }, - "is-weakref": { - "version": "1.0.2", - "requires": { - "call-bind": "^1.0.2" - } - }, - "is-weakset": { - "version": "2.0.2", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" - } - }, - "is-windows": { - "version": "1.0.2", - "dev": true - }, - "is-wsl": { - "version": "2.2.0", - "dev": true, - "requires": { - "is-docker": "^2.0.0" - } - }, - "isarray": { - "version": "1.0.0", - "dev": true - }, - "isbinaryfile": { - "version": "4.0.10", - "dev": true - }, - "isexe": { - "version": "2.0.0" - }, - "iso-random-stream": { - "version": "2.0.2", - "requires": { - "events": "^3.3.0", - "readable-stream": "^3.4.0" - }, - "dependencies": { - "events": { - "version": "3.3.0" - }, - "readable-stream": { - "version": "3.6.0", - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } - } - }, - "iso-url": { - "version": "1.2.1" - }, - "isobject": { - "version": "3.0.1", - "dev": true - }, - "isomorphic-ws": { - "version": "4.0.1", - "requires": {} - }, - "isstream": { - "version": "0.1.2" - }, - "istanbul-lib-coverage": { - "version": "3.2.0", - "dev": true - }, - "istanbul-lib-hook": { - "version": "3.0.0", - "dev": true, - "requires": { - "append-transform": "^2.0.0" - } - }, - "istanbul-lib-instrument": { - "version": "4.0.3", - "dev": true, - "requires": { - "@babel/core": "^7.7.5", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.0.0", - "semver": "^6.3.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "dev": true - } - } - }, - "istanbul-lib-processinfo": { - "version": "2.0.3", - "dev": true, - "requires": { - "archy": "^1.0.0", - "cross-spawn": "^7.0.3", - "istanbul-lib-coverage": "^3.2.0", - "p-map": "^3.0.0", - "rimraf": "^3.0.0", - "uuid": "^8.3.2" - }, - "dependencies": { - "p-map": { - "version": "3.0.0", - "dev": true, - "requires": { - "aggregate-error": "^3.0.0" - } - } - } - }, - "istanbul-lib-report": { - "version": "3.0.0", - "dev": true, - "requires": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^3.0.0", - "supports-color": "^7.1.0" - }, - "dependencies": { - "make-dir": { - "version": "3.1.0", - "dev": true, - "requires": { - "semver": "^6.0.0" - } - }, - "semver": { - "version": "6.3.0", - "dev": true - } - } - }, - "istanbul-lib-source-maps": { - "version": "4.0.1", - "dev": true, - "requires": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0", - "source-map": "^0.6.1" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "dev": true - } - } - }, - "istanbul-reports": { - "version": "3.1.5", - "dev": true, - "requires": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" - } - }, - "it-all": { - "version": "1.0.6" - }, - "it-buffer": { - "version": "0.1.3", - "requires": { - "bl": "^5.0.0", - "buffer": "^6.0.3" - }, - "dependencies": { - "bl": { - "version": "5.1.0", - "requires": { - "buffer": "^6.0.3", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - } - }, - "readable-stream": { - "version": "3.6.0", - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } - } - }, - "it-drain": { - "version": "1.0.5" - }, - "it-filter": { - "version": "1.0.3" - }, - "it-first": { - "version": "1.0.7" - }, - "it-glob": { - "version": "0.0.14", - "requires": { - "@types/minimatch": "^3.0.4", - "minimatch": "^3.0.4" - } - }, - "it-goodbye": { - "version": "2.0.2", - "requires": { - "buffer": "^5.6.0" - }, - "dependencies": { - "buffer": { - "version": "5.7.1", - "requires": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - } - } - }, - "it-handshake": { - "version": "2.0.0", - "requires": { - "it-pushable": "^1.4.0", - "it-reader": "^3.0.0", - "p-defer": "^3.0.0" - } - }, - "it-length-prefixed": { - "version": "5.0.3", - "requires": { - "bl": "^5.0.0", - "buffer": "^6.0.3", - "varint": "^6.0.0" - }, - "dependencies": { - "bl": { - "version": "5.1.0", - "requires": { - "buffer": "^6.0.3", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - } - }, - "readable-stream": { - "version": "3.6.0", - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } - } - }, - "it-map": { - "version": "1.0.6" - }, - "it-merge": { - "version": "1.0.0", - "requires": { - "it-pushable": "^1.4.0" - } - }, - "it-pair": { - "version": "1.0.0", - "requires": { - "get-iterator": "^1.0.2" - } - }, - "it-pb-rpc": { - "version": "0.1.13", - "requires": { - "is-buffer": "^2.0.5", - "it-handshake": "^2.0.0", - "it-length-prefixed": "^5.0.2" - } - }, - "it-pipe": { - "version": "1.1.0" - }, - "it-protocol-buffers": { - "version": "0.2.1", - "requires": { - "it-buffer": "^0.1.1", - "it-length-prefixed": "^3.0.0" - }, - "dependencies": { - "bl": { - "version": "4.1.0", - "requires": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - } - }, - "buffer": { - "version": "5.7.1", - "requires": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, - "it-length-prefixed": { - "version": "3.1.0", - "requires": { - "@types/bl": "^2.1.0", - "bl": "^4.0.2", - "buffer": "^5.5.0", - "varint": "^5.0.0" - } - }, - "readable-stream": { - "version": "3.6.0", - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, - "varint": { - "version": "5.0.2" - } - } - }, - "it-pushable": { - "version": "1.4.2", - "requires": { - "fast-fifo": "^1.0.0" - } - }, - "it-reader": { - "version": "3.0.0", - "requires": { - "bl": "^5.0.0" - }, - "dependencies": { - "bl": { - "version": "5.1.0", - "requires": { - "buffer": "^6.0.3", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - } - }, - "readable-stream": { - "version": "3.6.0", - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } - } - }, - "it-take": { - "version": "1.0.0" - }, - "it-to-stream": { - "version": "1.0.0", - "requires": { - "buffer": "^6.0.3", - "fast-fifo": "^1.0.0", - "get-iterator": "^1.0.2", - "p-defer": "^3.0.0", - "p-fifo": "^1.0.0", - "readable-stream": "^3.6.0" - }, - "dependencies": { - "readable-stream": { - "version": "3.6.0", - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } - } - }, - "it-ws": { - "version": "4.0.0", - "requires": { - "buffer": "^6.0.3", - "event-iterator": "^2.0.0", - "iso-url": "^1.1.2", - "ws": "^7.3.1" - } - }, - "jayson": { - "version": "4.0.0", - "requires": { - "@types/connect": "^3.4.33", - "@types/node": "^12.12.54", - "@types/ws": "^7.4.4", - "commander": "^2.20.3", - "delay": "^5.0.0", - "es6-promisify": "^5.0.0", - "eyes": "^0.1.8", - "isomorphic-ws": "^4.0.1", - "json-stringify-safe": "^5.0.1", - "JSONStream": "^1.3.5", - "uuid": "^8.3.2", - "ws": "^7.4.5" - }, - "dependencies": { - "@types/node": { - "version": "12.20.55" - }, - "commander": { - "version": "2.20.3" - } - } - }, - "jest-worker": { - "version": "27.5.1", - "dev": true, - "requires": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "dependencies": { - "supports-color": { - "version": "8.1.1", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "js-sdsl": { - "version": "4.1.5" - }, - "js-sha3": { - "version": "0.8.0" - }, - "js-tokens": { - "version": "4.0.0", - "dev": true - }, - "js-yaml": { - "version": "4.1.0", - "dev": true, - "requires": { - "argparse": "^2.0.1" - } - }, - "jsbn": { - "version": "1.1.0" - }, - "jsesc": { - "version": "2.5.2", - "dev": true - }, - "json-parse-better-errors": { - "version": "1.0.2", - "dev": true - }, - "json-parse-even-better-errors": { - "version": "2.3.1", - "dev": true - }, - "json-schema": { - "version": "0.4.0" - }, - "json-schema-traverse": { - "version": "0.4.1" - }, - "json-stable-stringify": { - "version": "0.0.1", - "dev": true, - "requires": { - "jsonify": "~0.0.0" - } - }, - "json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "dev": true - }, - "json-stringify-safe": { - "version": "5.0.1" - }, - "json5": { - "version": "2.2.1", - "dev": true - }, - "jsonc-parser": { - "version": "3.2.0", - "dev": true - }, - "jsonfile": { - "version": "6.1.0", - "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" - } - }, - "jsonify": { - "version": "0.0.1", - "dev": true - }, - "jsonparse": { - "version": "1.3.1" - }, - "jsonpointer": { - "version": "5.0.1", - "dev": true - }, - "JSONStream": { - "version": "1.3.5", - "requires": { - "jsonparse": "^1.2.0", - "through": ">=2.2.7 <3" - } - }, - "jsonstream2": { - "version": "1.1.2", - "dev": true, - "requires": { - "jsonparse": "0.0.6", - "through2": "^0.6.1", - "type-component": "0.0.1" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "dev": true - }, - "jsonparse": { - "version": "0.0.6", - "dev": true - }, - "readable-stream": { - "version": "1.0.34", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "string_decoder": { - "version": "0.10.31", - "dev": true - }, - "through2": { - "version": "0.6.5", - "dev": true, - "requires": { - "readable-stream": ">=1.0.33-1 <1.1.0-0", - "xtend": ">=4.0.0 <4.1.0-0" - } - } - } - }, - "jsprim": { - "version": "1.4.2", - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.4.0", - "verror": "1.10.0" - } - }, - "jsx-ast-utils": { - "version": "3.3.3", - "dev": true, - "requires": { - "array-includes": "^3.1.5", - "object.assign": "^4.1.3" - } - }, - "just-extend": { - "version": "4.2.1" - }, - "jwt-simple": { - "version": "0.5.6" - }, - "k-bucket": { - "version": "5.1.0", - "requires": { - "randombytes": "^2.1.0" - } - }, - "karma": { - "version": "6.4.0", - "dev": true, - "requires": { - "@colors/colors": "1.5.0", - "body-parser": "^1.19.0", - "braces": "^3.0.2", - "chokidar": "^3.5.1", - "connect": "^3.7.0", - "di": "^0.0.1", - "dom-serialize": "^2.2.1", - "glob": "^7.1.7", - "graceful-fs": "^4.2.6", - "http-proxy": "^1.18.1", - "isbinaryfile": "^4.0.8", - "lodash": "^4.17.21", - "log4js": "^6.4.1", - "mime": "^2.5.2", - "minimatch": "^3.0.4", - "mkdirp": "^0.5.5", - "qjobs": "^1.2.0", - "range-parser": "^1.2.1", - "rimraf": "^3.0.2", - "socket.io": "^4.4.1", - "source-map": "^0.6.1", - "tmp": "^0.2.1", - "ua-parser-js": "^0.7.30", - "yargs": "^16.1.1" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "dev": true - } - } - }, - "karma-chrome-launcher": { - "version": "3.1.1", - "dev": true, - "requires": { - "which": "^1.2.1" - } - }, - "karma-firefox-launcher": { - "version": "2.1.2", - "dev": true, - "requires": { - "is-wsl": "^2.2.0", - "which": "^2.0.1" - }, - "dependencies": { - "which": { - "version": "2.0.2", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - } - } - }, - "karma-tap": { - "version": "4.2.0", - "dev": true, - "requires": { - "babel-polyfill": "^6.26.0" - } - }, - "karma-typescript": { - "version": "5.5.3", - "dev": true, - "requires": { - "acorn": "^8.1.0", - "acorn-walk": "^8.0.2", - "assert": "^2.0.0", - "async": "^3.0.1", - "browser-resolve": "^2.0.0", - "browserify-zlib": "^0.2.0", - "buffer": "^5.4.3", - "combine-source-map": "^0.8.0", - "console-browserify": "^1.2.0", - "constants-browserify": "^1.0.0", - "convert-source-map": "^1.7.0", - "crypto-browserify": "^3.12.0", - "diff": "^4.0.1", - "domain-browser": "^4.16.0", - "events": "^3.2.0", - "glob": "^7.1.6", - "https-browserify": "^1.0.0", - "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-instrument": "^4.0.0", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^4.0.0", - "istanbul-reports": "^3.0.0", - "json-stringify-safe": "^5.0.1", - "lodash": "^4.17.19", - "log4js": "^6.3.0", - "minimatch": "^3.0.4", - "os-browserify": "^0.3.0", - "pad": "^3.2.0", - "path-browserify": "^1.0.0", - "process": "^0.11.10", - "punycode": "^2.1.1", - "querystring-es3": "^0.2.1", - "readable-stream": "^3.1.1", - "source-map": "^0.7.3", - "stream-browserify": "^3.0.0", - "stream-http": "^3.1.0", - "string_decoder": "^1.3.0", - "timers-browserify": "^2.0.11", - "tmp": "^0.2.1", - "tty-browserify": "^0.0.1", - "url": "^0.11.0", - "util": "^0.12.1", - "vm-browserify": "^1.1.2" - }, - "dependencies": { - "acorn-walk": { - "version": "8.2.0", - "dev": true - }, - "assert": { - "version": "2.0.0", - "dev": true, - "requires": { - "es6-object-assign": "^1.1.0", - "is-nan": "^1.2.1", - "object-is": "^1.0.1", - "util": "^0.12.0" - } - }, - "buffer": { - "version": "5.7.1", - "dev": true, - "requires": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, - "convert-source-map": { - "version": "1.9.0", - "dev": true - }, - "domain-browser": { - "version": "4.22.0", - "dev": true - }, - "events": { - "version": "3.3.0", - "dev": true - }, - "path-browserify": { - "version": "1.0.1", - "dev": true - }, - "punycode": { - "version": "2.1.1", - "dev": true - }, - "readable-stream": { - "version": "3.6.0", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, - "source-map": { - "version": "0.7.4", - "dev": true - }, - "timers-browserify": { - "version": "2.0.12", - "dev": true, - "requires": { - "setimmediate": "^1.0.4" - } - } - } - }, - "karma-typescript-es6-transform": { - "version": "5.5.3", - "dev": true, - "requires": { - "@babel/core": "^7.11.1", - "@babel/preset-env": "^7.11.0", - "acorn": "^8.1.0", - "acorn-walk": "^8.0.2", - "log4js": "^6.3.0", - "magic-string": "^0.25.7" - }, - "dependencies": { - "acorn-walk": { - "version": "8.2.0", - "dev": true - } - } - }, - "keypair": { - "version": "1.0.4" - }, - "kind-of": { - "version": "6.0.3", - "dev": true - }, - "kuler": { - "version": "2.0.0" - }, - "labeled-stream-splicer": { - "version": "2.0.2", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "stream-splicer": "^2.0.0" - } - }, - "language-subtag-registry": { - "version": "0.3.22", - "dev": true - }, - "language-tags": { - "version": "1.0.5", - "dev": true, - "requires": { - "language-subtag-registry": "~0.3.2" - } - }, - "level": { - "version": "8.0.0", - "requires": { - "browser-level": "^1.0.1", - "classic-level": "^1.2.0" - } - }, - "level-codec": { - "version": "10.0.0", - "dev": true, - "requires": { - "buffer": "^6.0.3" - } - }, - "level-concat-iterator": { - "version": "3.1.0", - "dev": true, - "requires": { - "catering": "^2.1.0" - } - }, - "level-errors": { - "version": "3.0.1", - "dev": true - }, - "level-iterator-stream": { - "version": "5.0.0", - "dev": true, - "requires": { - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - }, - "dependencies": { - "readable-stream": { - "version": "3.6.0", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } - } - }, - "level-js": { - "version": "6.1.0", - "dev": true, - "requires": { - "abstract-leveldown": "^7.2.0", - "buffer": "^6.0.3", - "inherits": "^2.0.3", - "ltgt": "^2.1.2", - "run-parallel-limit": "^1.1.0" - } - }, - "level-legacy": { - "version": "npm:level@7.0.1", - "dev": true, - "requires": { - "level-js": "^6.1.0", - "level-packager": "^6.0.1", - "leveldown": "^6.1.0" - } - }, - "level-mem": { - "version": "6.0.1", - "dev": true, - "requires": { - "level-packager": "^6.0.1", - "memdown": "^6.1.1" - } - }, - "level-packager": { - "version": "6.0.1", - "dev": true, - "requires": { - "encoding-down": "^7.1.0", - "levelup": "^5.1.1" - } - }, - "level-supports": { - "version": "4.0.1" - }, - "level-transcoder": { - "version": "1.0.1", - "requires": { - "buffer": "^6.0.3", - "module-error": "^1.0.1" - } - }, - "leveldown": { - "version": "6.1.1", - "dev": true, - "requires": { - "abstract-leveldown": "^7.2.0", - "napi-macros": "~2.0.0", - "node-gyp-build": "^4.3.0" - } - }, - "levelup": { - "version": "5.1.1", - "dev": true, - "requires": { - "catering": "^2.0.0", - "deferred-leveldown": "^7.0.0", - "level-errors": "^3.0.1", - "level-iterator-stream": "^5.0.0", - "level-supports": "^2.0.1", - "queue-microtask": "^1.2.3" - }, - "dependencies": { - "level-supports": { - "version": "2.1.0", - "dev": true - } - } - }, - "levn": { - "version": "0.4.1", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - } - }, - "libp2p": { - "version": "0.30.13", - "requires": { - "@motrix/nat-api": "^0.3.1", - "abort-controller": "^3.0.0", - "aggregate-error": "^3.1.0", - "any-signal": "^2.1.1", - "bignumber.js": "^9.0.1", - "cids": "^1.1.5", - "class-is": "^1.1.0", - "debug": "^4.3.1", - "err-code": "^2.0.0", - "es6-promisify": "^6.1.1", - "events": "^3.2.0", - "hashlru": "^2.3.0", - "interface-datastore": "^3.0.3", - "ipfs-utils": "^6.0.0", - "it-all": "^1.0.4", - "it-buffer": "^0.1.2", - "it-drain": "^1.0.3", - "it-filter": "^1.0.1", - "it-first": "^1.0.4", - "it-handshake": "^1.0.2", - "it-length-prefixed": "^3.1.0", - "it-map": "^1.0.4", - "it-merge": "1.0.0", - "it-pipe": "^1.1.0", - "it-protocol-buffers": "^0.2.0", - "it-take": "1.0.0", - "libp2p-crypto": "^0.19.0", - "libp2p-interfaces": "^0.8.1", - "libp2p-utils": "^0.2.2", - "mafmt": "^8.0.0", - "merge-options": "^3.0.4", - "moving-average": "^1.0.0", - "multiaddr": "^8.1.0", - "multicodec": "^2.1.0", - "multihashing-async": "^2.0.1", - "multistream-select": "^1.0.0", - "mutable-proxy": "^1.0.0", - "node-forge": "^0.10.0", - "p-any": "^3.0.0", - "p-fifo": "^1.0.0", - "p-retry": "^4.2.0", - "p-settle": "^4.0.1", - "peer-id": "^0.14.2", - "private-ip": "^2.0.0", - "protons": "^2.0.0", - "retimer": "^2.0.0", - "sanitize-filename": "^1.6.3", - "set-delayed-interval": "^1.0.0", - "streaming-iterables": "^5.0.2", - "timeout-abort-controller": "^1.1.1", - "uint8arrays": "^2.1.3", - "varint": "^6.0.0", - "xsalsa20": "^1.0.2" - }, - "dependencies": { - "bl": { - "version": "4.1.0", - "requires": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - } - }, - "buffer": { - "version": "5.7.1", - "requires": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, - "delay": { - "version": "4.4.1" - }, - "es6-promisify": { - "version": "6.1.1" - }, - "events": { - "version": "3.3.0" - }, - "it-handshake": { - "version": "1.0.2", - "requires": { - "it-pushable": "^1.4.0", - "it-reader": "^2.0.0", - "p-defer": "^3.0.0" - } - }, - "it-length-prefixed": { - "version": "3.1.0", - "requires": { - "@types/bl": "^2.1.0", - "bl": "^4.0.2", - "buffer": "^5.5.0", - "varint": "^5.0.0" - }, - "dependencies": { - "varint": { - "version": "5.0.2" - } - } - }, - "it-reader": { - "version": "2.1.0", - "requires": { - "bl": "^4.0.0" - } - }, - "libp2p-interfaces": { - "version": "0.8.4", - "requires": { - "@types/bl": "^2.1.0", - "abort-controller": "^3.0.0", - "abortable-iterator": "^3.0.0", - "chai": "^4.2.0", - "chai-checkmark": "^1.0.1", - "debug": "^4.3.1", - "delay": "^4.4.0", - "detect-node": "^2.0.4", - "dirty-chai": "^2.0.1", - "err-code": "^2.0.3", - "it-goodbye": "^2.0.2", - "it-length-prefixed": "^3.1.0", - "it-pair": "^1.0.0", - "it-pipe": "^1.1.0", - "it-pushable": "^1.4.0", - "libp2p-crypto": "^0.19.0", - "libp2p-tcp": "^0.15.0", - "multiaddr": "^8.1.2", - "multibase": "^3.1.1", - "multihashes": "^3.1.1", - "p-defer": "^3.0.0", - "p-limit": "^3.1.0", - "p-wait-for": "^3.2.0", - "peer-id": "^0.14.2", - "protons": "^2.0.0", - "sinon": "^9.2.4", - "streaming-iterables": "^5.0.4", - "uint8arrays": "^2.0.5" - } - }, - "multiaddr": { - "version": "8.1.2", - "requires": { - "cids": "^1.0.0", - "class-is": "^1.1.0", - "dns-over-http-resolver": "^1.0.0", - "err-code": "^2.0.3", - "is-ip": "^3.1.0", - "multibase": "^3.0.0", - "uint8arrays": "^1.1.0", - "varint": "^5.0.0" - }, - "dependencies": { - "uint8arrays": { - "version": "1.1.0", - "requires": { - "multibase": "^3.0.0", - "web-encoding": "^1.0.2" - } - }, - "varint": { - "version": "5.0.2" - } - } - }, - "multibase": { - "version": "3.1.2", - "requires": { - "@multiformats/base-x": "^4.0.1", - "web-encoding": "^1.0.6" - } - }, - "multihashes": { - "version": "3.1.2", - "requires": { - "multibase": "^3.1.0", - "uint8arrays": "^2.0.5", - "varint": "^6.0.0" - } - }, - "readable-stream": { - "version": "3.6.0", - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, - "uint8arrays": { - "version": "2.1.10", - "requires": { - "multiformats": "^9.4.2" - } - } - } - }, - "libp2p-bootstrap": { - "version": "0.14.0", - "requires": { - "debug": "^4.3.1", - "mafmt": "^10.0.0", - "multiaddr": "^10.0.0", - "peer-id": "^0.16.0" - }, - "dependencies": { - "err-code": { - "version": "3.0.1" - }, - "libp2p-crypto": { - "version": "0.21.2", - "requires": { - "@noble/ed25519": "^1.5.1", - "@noble/secp256k1": "^1.3.0", - "err-code": "^3.0.1", - "iso-random-stream": "^2.0.0", - "multiformats": "^9.4.5", - "node-forge": "^1.2.1", - "protobufjs": "^6.11.2", - "uint8arrays": "^3.0.0" - } - }, - "mafmt": { - "version": "10.0.0", - "requires": { - "multiaddr": "^10.0.0" - } - }, - "node-forge": { - "version": "1.3.1" - }, - "peer-id": { - "version": "0.16.0", - "requires": { - "class-is": "^1.1.0", - "libp2p-crypto": "^0.21.0", - "multiformats": "^9.4.5", - "protobufjs": "^6.10.2", - "uint8arrays": "^3.0.0" - } - } - } - }, - "libp2p-crypto": { - "version": "0.19.7", - "requires": { - "err-code": "^3.0.1", - "is-typedarray": "^1.0.0", - "iso-random-stream": "^2.0.0", - "keypair": "^1.0.1", - "multiformats": "^9.4.5", - "node-forge": "^0.10.0", - "pem-jwk": "^2.0.0", - "protobufjs": "^6.11.2", - "secp256k1": "^4.0.0", - "uint8arrays": "^3.0.0", - "ursa-optional": "^0.10.1" - }, - "dependencies": { - "err-code": { - "version": "3.0.1" - } - } - }, - "libp2p-interfaces": { - "version": "1.3.1", - "requires": { - "abort-controller": "^3.0.0", - "abortable-iterator": "^3.0.0", - "debug": "^4.3.1", - "err-code": "^3.0.1", - "it-length-prefixed": "^5.0.2", - "it-pipe": "^1.1.0", - "it-pushable": "^1.4.2", - "libp2p-crypto": "^0.20.0", - "multiaddr": "^10.0.0", - "multiformats": "^9.1.2", - "p-queue": "^6.6.2", - "peer-id": "^0.15.4", - "protobufjs": "^6.10.2", - "uint8arrays": "^3.0.0" - }, - "dependencies": { - "err-code": { - "version": "3.0.1" - }, - "libp2p-crypto": { - "version": "0.20.0", - "requires": { - "err-code": "^3.0.1", - "iso-random-stream": "^2.0.0", - "keypair": "^1.0.4", - "multiformats": "^9.4.5", - "noble-ed25519": "^1.2.6", - "noble-secp256k1": "^1.2.10", - "node-forge": "^0.10.0", - "pem-jwk": "^2.0.0", - "protobufjs": "^6.11.2", - "uint8arrays": "^3.0.0", - "ursa-optional": "^0.10.1" - } - }, - "peer-id": { - "version": "0.15.4", - "requires": { - "class-is": "^1.1.0", - "libp2p-crypto": "^0.20.0", - "minimist": "^1.2.5", - "multiformats": "^9.4.5", - "protobufjs": "^6.10.2", - "uint8arrays": "^3.0.0" - } - } - } - }, - "libp2p-kad-dht": { - "version": "0.20.6", - "requires": { - "abort-controller": "^3.0.0", - "async": "^2.6.2", - "base32.js": "~0.1.0", - "cids": "^1.1.5", - "debug": "^4.3.1", - "err-code": "^2.0.3", - "hashlru": "^2.3.0", - "heap": "~0.2.6", - "interface-datastore": "^3.0.3", - "it-length-prefixed": "^3.1.0", - "it-pipe": "^1.1.0", - "k-bucket": "^5.0.0", - "libp2p-crypto": "^0.19.0", - "libp2p-interfaces": "^0.8.2", - "libp2p-record": "^0.9.0", - "multiaddr": "^8.1.2", - "multihashing-async": "^2.0.1", - "p-filter": "^2.1.0", - "p-map": "^4.0.0", - "p-queue": "^6.6.2", - "p-timeout": "^4.1.0", - "p-times": "^3.0.0", - "peer-id": "^0.14.2", - "promise-to-callback": "^1.0.0", - "protons": "^2.0.0", - "streaming-iterables": "^5.0.4", - "uint8arrays": "^2.0.5", - "varint": "^5.0.0", - "xor-distance": "^2.0.0" - }, - "dependencies": { - "async": { - "version": "2.6.4", - "requires": { - "lodash": "^4.17.14" - } - }, - "bl": { - "version": "4.1.0", - "requires": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - } - }, - "buffer": { - "version": "5.7.1", - "requires": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, - "delay": { - "version": "4.4.1" - }, - "it-length-prefixed": { - "version": "3.1.0", - "requires": { - "@types/bl": "^2.1.0", - "bl": "^4.0.2", - "buffer": "^5.5.0", - "varint": "^5.0.0" - } - }, - "libp2p-interfaces": { - "version": "0.8.4", - "requires": { - "@types/bl": "^2.1.0", - "abort-controller": "^3.0.0", - "abortable-iterator": "^3.0.0", - "chai": "^4.2.0", - "chai-checkmark": "^1.0.1", - "debug": "^4.3.1", - "delay": "^4.4.0", - "detect-node": "^2.0.4", - "dirty-chai": "^2.0.1", - "err-code": "^2.0.3", - "it-goodbye": "^2.0.2", - "it-length-prefixed": "^3.1.0", - "it-pair": "^1.0.0", - "it-pipe": "^1.1.0", - "it-pushable": "^1.4.0", - "libp2p-crypto": "^0.19.0", - "libp2p-tcp": "^0.15.0", - "multiaddr": "^8.1.2", - "multibase": "^3.1.1", - "multihashes": "^3.1.1", - "p-defer": "^3.0.0", - "p-limit": "^3.1.0", - "p-wait-for": "^3.2.0", - "peer-id": "^0.14.2", - "protons": "^2.0.0", - "sinon": "^9.2.4", - "streaming-iterables": "^5.0.4", - "uint8arrays": "^2.0.5" - } - }, - "multiaddr": { - "version": "8.1.2", - "requires": { - "cids": "^1.0.0", - "class-is": "^1.1.0", - "dns-over-http-resolver": "^1.0.0", - "err-code": "^2.0.3", - "is-ip": "^3.1.0", - "multibase": "^3.0.0", - "uint8arrays": "^1.1.0", - "varint": "^5.0.0" - }, - "dependencies": { - "uint8arrays": { - "version": "1.1.0", - "requires": { - "multibase": "^3.0.0", - "web-encoding": "^1.0.2" - } - } - } - }, - "multibase": { - "version": "3.1.2", - "requires": { - "@multiformats/base-x": "^4.0.1", - "web-encoding": "^1.0.6" - } - }, - "multihashes": { - "version": "3.1.2", - "requires": { - "multibase": "^3.1.0", - "uint8arrays": "^2.0.5", - "varint": "^6.0.0" - }, - "dependencies": { - "varint": { - "version": "6.0.0" - } - } - }, - "readable-stream": { - "version": "3.6.0", - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, - "uint8arrays": { - "version": "2.1.10", - "requires": { - "multiformats": "^9.4.2" - } - }, - "varint": { - "version": "5.0.2" - } - } - }, - "libp2p-mplex": { - "version": "0.10.7", - "requires": { - "abortable-iterator": "^3.0.2", - "bl": "^5.0.0", - "debug": "^4.3.1", - "err-code": "^3.0.1", - "it-pipe": "^1.1.0", - "it-pushable": "^1.4.1", - "varint": "^6.0.0" - }, - "dependencies": { - "bl": { - "version": "5.1.0", - "requires": { - "buffer": "^6.0.3", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - } - }, - "err-code": { - "version": "3.0.1" - }, - "readable-stream": { - "version": "3.6.0", - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } - } - }, - "libp2p-record": { - "version": "0.9.0", - "requires": { - "err-code": "^2.0.0", - "multihashes": "^3.0.1", - "multihashing-async": "^2.0.1", - "protons": "^2.0.0", - "uint8arrays": "^1.1.0" - }, - "dependencies": { - "multibase": { - "version": "3.1.2", - "requires": { - "@multiformats/base-x": "^4.0.1", - "web-encoding": "^1.0.6" - } - }, - "multihashes": { - "version": "3.1.2", - "requires": { - "multibase": "^3.1.0", - "uint8arrays": "^2.0.5", - "varint": "^6.0.0" - }, - "dependencies": { - "uint8arrays": { - "version": "2.1.10", - "requires": { - "multiformats": "^9.4.2" - } - } - } - }, - "uint8arrays": { - "version": "1.1.0", - "requires": { - "multibase": "^3.0.0", - "web-encoding": "^1.0.2" - } - } - } - }, - "libp2p-tcp": { - "version": "0.15.4", - "requires": { - "abortable-iterator": "^3.0.0", - "class-is": "^1.1.0", - "debug": "^4.3.1", - "err-code": "^3.0.1", - "libp2p-utils": "^0.3.0", - "mafmt": "^9.0.0", - "multiaddr": "^9.0.1", - "stream-to-it": "^0.2.2" - }, - "dependencies": { - "err-code": { - "version": "3.0.1" - }, - "ip-address": { - "version": "7.1.0", - "requires": { - "jsbn": "1.1.0", - "sprintf-js": "1.1.2" - } - }, - "libp2p-utils": { - "version": "0.3.1", - "requires": { - "abortable-iterator": "^3.0.0", - "debug": "^4.3.0", - "err-code": "^3.0.1", - "ip-address": "^7.1.0", - "is-loopback-addr": "^1.0.0", - "multiaddr": "^9.0.1", - "private-ip": "^2.1.1" - } - }, - "mafmt": { - "version": "9.0.0", - "requires": { - "multiaddr": "^9.0.1" - } - }, - "multiaddr": { - "version": "9.0.2", - "requires": { - "cids": "^1.0.0", - "dns-over-http-resolver": "^1.0.0", - "err-code": "^3.0.1", - "is-ip": "^3.1.0", - "multibase": "^4.0.2", - "uint8arrays": "^2.1.3", - "varint": "^6.0.0" - } - }, - "uint8arrays": { - "version": "2.1.10", - "requires": { - "multiformats": "^9.4.2" - } - } - } - }, - "libp2p-utils": { - "version": "0.2.3", - "requires": { - "abortable-iterator": "^3.0.0", - "debug": "^4.2.0", - "err-code": "^2.0.3", - "ip-address": "^6.1.0", - "is-loopback-addr": "^1.0.0", - "multiaddr": "^8.0.0", - "private-ip": "^2.1.1" - }, - "dependencies": { - "multiaddr": { - "version": "8.1.2", - "requires": { - "cids": "^1.0.0", - "class-is": "^1.1.0", - "dns-over-http-resolver": "^1.0.0", - "err-code": "^2.0.3", - "is-ip": "^3.1.0", - "multibase": "^3.0.0", - "uint8arrays": "^1.1.0", - "varint": "^5.0.0" - } - }, - "multibase": { - "version": "3.1.2", - "requires": { - "@multiformats/base-x": "^4.0.1", - "web-encoding": "^1.0.6" - } - }, - "uint8arrays": { - "version": "1.1.0", - "requires": { - "multibase": "^3.0.0", - "web-encoding": "^1.0.2" - } - }, - "varint": { - "version": "5.0.2" - } - } - }, - "libp2p-websockets": { - "version": "0.15.9", - "requires": { - "abortable-iterator": "^3.0.0", - "class-is": "^1.1.0", - "debug": "^4.3.1", - "err-code": "^3.0.1", - "ipfs-utils": "^8.1.2", - "it-ws": "^4.0.0", - "libp2p-utils": "^0.3.0", - "mafmt": "^9.0.0", - "multiaddr": "^9.0.1", - "multiaddr-to-uri": "^7.0.0", - "p-defer": "^3.0.0", - "p-timeout": "^4.1.0" - }, - "dependencies": { - "err-code": { - "version": "3.0.1" - }, - "ip-address": { - "version": "7.1.0", - "requires": { - "jsbn": "1.1.0", - "sprintf-js": "1.1.2" - } - }, - "ipfs-utils": { - "version": "8.1.6", - "requires": { - "abort-controller": "^3.0.0", - "any-signal": "^2.1.0", - "buffer": "^6.0.1", - "electron-fetch": "^1.7.2", - "err-code": "^3.0.1", - "is-electron": "^2.2.0", - "iso-url": "^1.1.5", - "it-glob": "~0.0.11", - "it-to-stream": "^1.0.0", - "merge-options": "^3.0.4", - "nanoid": "^3.1.20", - "native-abort-controller": "^1.0.3", - "native-fetch": "^3.0.0", - "node-fetch": "https://registry.npmjs.org/@achingbrain/node-fetch/-/node-fetch-2.6.7.tgz", - "react-native-fetch-api": "^2.0.0", - "stream-to-it": "^0.2.2" - } - }, - "libp2p-utils": { - "version": "0.3.1", - "requires": { - "abortable-iterator": "^3.0.0", - "debug": "^4.3.0", - "err-code": "^3.0.1", - "ip-address": "^7.1.0", - "is-loopback-addr": "^1.0.0", - "multiaddr": "^9.0.1", - "private-ip": "^2.1.1" - } - }, - "mafmt": { - "version": "9.0.0", - "requires": { - "multiaddr": "^9.0.1" - } - }, - "multiaddr": { - "version": "9.0.2", - "requires": { - "cids": "^1.0.0", - "dns-over-http-resolver": "^1.0.0", - "err-code": "^3.0.1", - "is-ip": "^3.1.0", - "multibase": "^4.0.2", - "uint8arrays": "^2.1.3", - "varint": "^6.0.0" - } - }, - "node-fetch": { - "version": "npm:@achingbrain/node-fetch@2.6.7" - }, - "uint8arrays": { - "version": "2.1.10", - "requires": { - "multiformats": "^9.4.2" - } - } - } - }, - "lilconfig": { - "version": "2.0.5", - "dev": true - }, - "lint-staged": { - "version": "13.0.3", - "dev": true, - "requires": { - "cli-truncate": "^3.1.0", - "colorette": "^2.0.17", - "commander": "^9.3.0", - "debug": "^4.3.4", - "execa": "^6.1.0", - "lilconfig": "2.0.5", - "listr2": "^4.0.5", - "micromatch": "^4.0.5", - "normalize-path": "^3.0.0", - "object-inspect": "^1.12.2", - "pidtree": "^0.6.0", - "string-argv": "^0.3.1", - "yaml": "^2.1.1" - }, - "dependencies": { - "commander": { - "version": "9.4.1", - "dev": true - }, - "execa": { - "version": "6.1.0", - "dev": true, - "requires": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.1", - "human-signals": "^3.0.1", - "is-stream": "^3.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^5.1.0", - "onetime": "^6.0.0", - "signal-exit": "^3.0.7", - "strip-final-newline": "^3.0.0" - } - }, - "human-signals": { - "version": "3.0.1", - "dev": true - }, - "is-stream": { - "version": "3.0.0", - "dev": true - }, - "mimic-fn": { - "version": "4.0.0", - "dev": true - }, - "npm-run-path": { - "version": "5.1.0", - "dev": true, - "requires": { - "path-key": "^4.0.0" - } - }, - "onetime": { - "version": "6.0.0", - "dev": true, - "requires": { - "mimic-fn": "^4.0.0" - } - }, - "path-key": { - "version": "4.0.0", - "dev": true - }, - "strip-final-newline": { - "version": "3.0.0", - "dev": true - } - } - }, - "listr2": { - "version": "4.0.5", - "dev": true, - "requires": { - "cli-truncate": "^2.1.0", - "colorette": "^2.0.16", - "log-update": "^4.0.0", - "p-map": "^4.0.0", - "rfdc": "^1.3.0", - "rxjs": "^7.5.5", - "through": "^2.3.8", - "wrap-ansi": "^7.0.0" - }, - "dependencies": { - "cli-truncate": { - "version": "2.1.0", - "dev": true, - "requires": { - "slice-ansi": "^3.0.0", - "string-width": "^4.2.0" - } - }, - "emoji-regex": { - "version": "8.0.0", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "dev": true - }, - "slice-ansi": { - "version": "3.0.0", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - } - }, - "string-width": { - "version": "4.2.3", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - } - } - }, - "lmdb": { - "version": "2.6.8", - "dev": true, - "requires": { - "@lmdb/lmdb-darwin-arm64": "2.6.8", - "@lmdb/lmdb-darwin-x64": "2.6.8", - "@lmdb/lmdb-linux-arm": "2.6.8", - "@lmdb/lmdb-linux-arm64": "2.6.8", - "@lmdb/lmdb-linux-x64": "2.6.8", - "@lmdb/lmdb-win32-x64": "2.6.8", - "msgpackr": "1.7.2", - "node-addon-api": "^4.3.0", - "node-gyp-build-optional-packages": "5.0.3", - "ordered-binary": "^1.4.0", - "weak-lru-cache": "^1.2.2" - } - }, - "load-json-file": { - "version": "4.0.0", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^4.0.0", - "pify": "^3.0.0", - "strip-bom": "^3.0.0" - }, - "dependencies": { - "strip-bom": { - "version": "3.0.0", - "dev": true - } - } - }, - "loader-runner": { - "version": "4.3.0", - "dev": true - }, - "loader-utils": { - "version": "2.0.3", - "dev": true, - "requires": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" - } - }, - "locate-path": { - "version": "6.0.0", - "dev": true, - "requires": { - "p-locate": "^5.0.0" - } - }, - "lodash": { - "version": "4.17.21" - }, - "lodash.camelcase": { - "version": "4.3.0", - "dev": true - }, - "lodash.cond": { - "version": "4.5.2", - "dev": true - }, - "lodash.debounce": { - "version": "4.0.8", - "dev": true - }, - "lodash.find": { - "version": "4.6.0" - }, - "lodash.flattendeep": { - "version": "4.4.0", - "dev": true - }, - "lodash.get": { - "version": "4.4.2" - }, - "lodash.kebabcase": { - "version": "4.1.1", - "dev": true - }, - "lodash.max": { - "version": "4.0.1" - }, - "lodash.memoize": { - "version": "3.0.4", - "dev": true - }, - "lodash.merge": { - "version": "4.6.2" - }, - "lodash.padstart": { - "version": "4.6.1" - }, - "lodash.repeat": { - "version": "4.1.0" - }, - "lodash.snakecase": { - "version": "4.1.1", - "dev": true - }, - "lodash.upperfirst": { - "version": "4.3.1", - "dev": true - }, - "log-update": { - "version": "4.0.0", - "dev": true, - "requires": { - "ansi-escapes": "^4.3.0", - "cli-cursor": "^3.1.0", - "slice-ansi": "^4.0.0", - "wrap-ansi": "^6.2.0" - }, - "dependencies": { - "emoji-regex": { - "version": "8.0.0", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "dev": true - }, - "slice-ansi": { - "version": "4.0.0", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - } - }, - "string-width": { - "version": "4.2.3", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "wrap-ansi": { - "version": "6.2.0", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - } - } - }, - "log4js": { - "version": "6.7.0", - "dev": true, - "requires": { - "date-format": "^4.0.14", - "debug": "^4.3.4", - "flatted": "^3.2.7", - "rfdc": "^1.3.0", - "streamroller": "^3.1.3" - } - }, - "logform": { - "version": "2.4.2", - "requires": { - "@colors/colors": "1.5.0", - "fecha": "^4.2.0", - "ms": "^2.1.1", - "safe-stable-stringify": "^2.3.1", - "triple-beam": "^1.3.0" - }, - "dependencies": { - "ms": { - "version": "2.1.3" - } - } - }, - "lolex": { - "version": "1.6.0", - "dev": true - }, - "long": { - "version": "4.0.0" - }, - "loupe": { - "version": "2.3.4", - "requires": { - "get-func-name": "^2.0.0" - } - }, - "lower-case": { - "version": "1.1.4", - "dev": true - }, - "lru-cache": { - "version": "7.18.3" - }, - "ltgt": { - "version": "2.2.1", - "dev": true - }, - "lunr": { - "version": "2.3.9", - "dev": true - }, - "mafmt": { - "version": "8.0.4", - "requires": { - "multiaddr": "^8.0.0" - }, - "dependencies": { - "multiaddr": { - "version": "8.1.2", - "requires": { - "cids": "^1.0.0", - "class-is": "^1.1.0", - "dns-over-http-resolver": "^1.0.0", - "err-code": "^2.0.3", - "is-ip": "^3.1.0", - "multibase": "^3.0.0", - "uint8arrays": "^1.1.0", - "varint": "^5.0.0" - } - }, - "multibase": { - "version": "3.1.2", - "requires": { - "@multiformats/base-x": "^4.0.1", - "web-encoding": "^1.0.6" - } - }, - "uint8arrays": { - "version": "1.1.0", - "requires": { - "multibase": "^3.0.0", - "web-encoding": "^1.0.2" - } - }, - "varint": { - "version": "5.0.2" - } - } - }, - "magic-string": { - "version": "0.25.9", - "dev": true, - "requires": { - "sourcemap-codec": "^1.4.8" - } - }, - "make-dir": { - "version": "1.3.0", - "dev": true, - "requires": { - "pify": "^3.0.0" - } - }, - "make-error": { - "version": "1.3.6", - "dev": true - }, - "marked": { - "version": "4.1.1", - "dev": true - }, - "mcl-wasm": { - "version": "0.7.9" - }, - "md5.js": { - "version": "1.3.5", - "dev": true, - "requires": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "media-typer": { - "version": "0.3.0" - }, - "memdown": { - "version": "6.1.1", - "dev": true, - "requires": { - "abstract-leveldown": "^7.2.0", - "buffer": "^6.0.3", - "functional-red-black-tree": "^1.0.1", - "inherits": "^2.0.1", - "ltgt": "^2.2.0" - } - }, - "memory-level": { - "version": "1.0.0", - "requires": { - "abstract-level": "^1.0.0", - "functional-red-black-tree": "^1.0.1", - "module-error": "^1.0.1" - } - }, - "memorystream": { - "version": "0.3.1", - "dev": true - }, - "merge-options": { - "version": "3.0.4", - "requires": { - "is-plain-obj": "^2.1.0" - } - }, - "merge-source-map": { - "version": "1.0.4", - "dev": true, - "requires": { - "source-map": "^0.5.6" - } - }, - "merge-stream": { - "version": "2.0.0" - }, - "merge2": { - "version": "1.4.1", - "dev": true - }, - "methods": { - "version": "1.1.2", - "dev": true - }, - "micro-bmark": { - "version": "0.2.0", - "dev": true - }, - "micromatch": { - "version": "4.0.5", - "dev": true, - "requires": { - "braces": "^3.0.2", - "picomatch": "^2.3.1" - } - }, - "miller-rabin": { - "version": "4.0.1", - "dev": true, - "requires": { - "bn.js": "^4.0.0", - "brorand": "^1.0.1" - }, - "dependencies": { - "bn.js": { - "version": "4.12.0", - "dev": true - } - } - }, - "mime": { - "version": "2.6.0", - "dev": true - }, - "mime-db": { - "version": "1.52.0" - }, - "mime-types": { - "version": "2.1.35", - "requires": { - "mime-db": "1.52.0" - } - }, - "mimic-fn": { - "version": "2.1.0" - }, - "minimalistic-assert": { - "version": "1.0.1" - }, - "minimalistic-crypto-utils": { - "version": "1.0.1" - }, - "minimatch": { - "version": "3.1.2", - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "1.2.7" - }, - "mkdirp": { - "version": "0.5.6", - "dev": true, - "requires": { - "minimist": "^1.2.6" - } - }, - "mkdirp-classic": { - "version": "0.5.3", - "dev": true - }, - "module-deps": { - "version": "6.2.3", - "dev": true, - "requires": { - "browser-resolve": "^2.0.0", - "cached-path-relative": "^1.0.2", - "concat-stream": "~1.6.0", - "defined": "^1.0.0", - "detective": "^5.2.0", - "duplexer2": "^0.1.2", - "inherits": "^2.0.1", - "JSONStream": "^1.0.3", - "parents": "^1.0.0", - "readable-stream": "^2.0.2", - "resolve": "^1.4.0", - "stream-combiner2": "^1.1.1", - "subarg": "^1.0.0", - "through2": "^2.0.0", - "xtend": "^4.0.0" - } - }, - "module-error": { - "version": "1.0.2" - }, - "moment": { - "version": "2.29.4" - }, - "morphdom": { - "version": "2.6.1", - "dev": true - }, - "moving-average": { - "version": "1.0.1" - }, - "ms": { - "version": "0.7.3" - }, - "msgpackr": { - "version": "1.7.2", - "dev": true, - "requires": { - "msgpackr-extract": "^2.1.2" - } - }, - "msgpackr-extract": { - "version": "2.1.2", - "dev": true, - "optional": true, - "requires": { - "@msgpackr-extract/msgpackr-extract-darwin-arm64": "2.1.2", - "@msgpackr-extract/msgpackr-extract-darwin-x64": "2.1.2", - "@msgpackr-extract/msgpackr-extract-linux-arm": "2.1.2", - "@msgpackr-extract/msgpackr-extract-linux-arm64": "2.1.2", - "@msgpackr-extract/msgpackr-extract-linux-x64": "2.1.2", - "@msgpackr-extract/msgpackr-extract-win32-x64": "2.1.2", - "node-gyp-build-optional-packages": "5.0.3" - } - }, - "multiaddr": { - "version": "10.0.1", - "requires": { - "dns-over-http-resolver": "^1.2.3", - "err-code": "^3.0.1", - "is-ip": "^3.1.0", - "multiformats": "^9.4.5", - "uint8arrays": "^3.0.0", - "varint": "^6.0.0" - }, - "dependencies": { - "err-code": { - "version": "3.0.1" - } - } - }, - "multiaddr-to-uri": { - "version": "7.0.0", - "requires": { - "multiaddr": "^9.0.1" - }, - "dependencies": { - "err-code": { - "version": "3.0.1" - }, - "multiaddr": { - "version": "9.0.2", - "requires": { - "cids": "^1.0.0", - "dns-over-http-resolver": "^1.0.0", - "err-code": "^3.0.1", - "is-ip": "^3.1.0", - "multibase": "^4.0.2", - "uint8arrays": "^2.1.3", - "varint": "^6.0.0" - } - }, - "uint8arrays": { - "version": "2.1.10", - "requires": { - "multiformats": "^9.4.2" - } - } - } - }, - "multibase": { - "version": "4.0.6", - "requires": { - "@multiformats/base-x": "^4.0.1" - } - }, - "multicodec": { - "version": "2.1.3", - "requires": { - "uint8arrays": "1.1.0", - "varint": "^6.0.0" - }, - "dependencies": { - "multibase": { - "version": "3.1.2", - "requires": { - "@multiformats/base-x": "^4.0.1", - "web-encoding": "^1.0.6" - } - }, - "uint8arrays": { - "version": "1.1.0", - "requires": { - "multibase": "^3.0.0", - "web-encoding": "^1.0.2" - } - } - } - }, - "multiformats": { - "version": "9.9.0" - }, - "multihashes": { - "version": "4.0.3", - "requires": { - "multibase": "^4.0.1", - "uint8arrays": "^3.0.0", - "varint": "^5.0.2" - }, - "dependencies": { - "varint": { - "version": "5.0.2" - } - } - }, - "multihashing-async": { - "version": "2.1.4", - "requires": { - "blakejs": "^1.1.0", - "err-code": "^3.0.0", - "js-sha3": "^0.8.0", - "multihashes": "^4.0.1", - "murmurhash3js-revisited": "^3.0.0", - "uint8arrays": "^3.0.0" - }, - "dependencies": { - "err-code": { - "version": "3.0.1" - } - } - }, - "multistream-select": { - "version": "1.0.0", - "requires": { - "bl": "^4.0.0", - "debug": "^4.1.1", - "err-code": "^2.0.0", - "it-handshake": "^1.0.2", - "it-length-prefixed": "^3.0.0", - "it-pipe": "^1.0.1", - "it-reader": "^2.0.0", - "p-defer": "^3.0.0", - "uint8arrays": "^1.1.0" - }, - "dependencies": { - "bl": { - "version": "4.1.0", - "requires": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - } - }, - "buffer": { - "version": "5.7.1", - "requires": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, - "it-handshake": { - "version": "1.0.2", - "requires": { - "it-pushable": "^1.4.0", - "it-reader": "^2.0.0", - "p-defer": "^3.0.0" - } - }, - "it-length-prefixed": { - "version": "3.1.0", - "requires": { - "@types/bl": "^2.1.0", - "bl": "^4.0.2", - "buffer": "^5.5.0", - "varint": "^5.0.0" - } - }, - "it-reader": { - "version": "2.1.0", - "requires": { - "bl": "^4.0.0" - } - }, - "multibase": { - "version": "3.1.2", - "requires": { - "@multiformats/base-x": "^4.0.1", - "web-encoding": "^1.0.6" - } - }, - "readable-stream": { - "version": "3.6.0", - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, - "uint8arrays": { - "version": "1.1.0", - "requires": { - "multibase": "^3.0.0", - "web-encoding": "^1.0.2" - } - }, - "varint": { - "version": "5.0.2" - } - } - }, - "murmurhash3js-revisited": { - "version": "3.0.0" - }, - "mutable-proxy": { - "version": "1.0.0" - }, - "mute-stream": { - "version": "0.0.5", - "dev": true - }, - "mutexify": { - "version": "1.4.0", - "dev": true, - "requires": { - "queue-tick": "^1.0.0" - } - }, - "nan": { - "version": "2.17.0" - }, - "nanoassert": { - "version": "1.1.0", - "dev": true - }, - "nanobench": { - "version": "2.1.1", - "dev": true, - "requires": { - "browser-process-hrtime": "^0.1.2", - "chalk": "^1.1.3", - "mutexify": "^1.1.0", - "pretty-hrtime": "^1.0.2" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "dev": true - }, - "ansi-styles": { - "version": "2.2.1", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "supports-color": { - "version": "2.0.0", - "dev": true - } - } - }, - "nanohtml": { - "version": "1.10.0", - "dev": true, - "requires": { - "acorn-node": "^1.8.2", - "camel-case": "^3.0.0", - "convert-source-map": "^1.5.1", - "estree-is-member-expression": "^1.0.0", - "hyperx": "^2.5.0", - "is-boolean-attribute": "0.0.1", - "nanoassert": "^1.1.0", - "nanobench": "^2.1.0", - "normalize-html-whitespace": "^0.2.0", - "through2": "^2.0.3", - "transform-ast": "^2.4.0" - }, - "dependencies": { - "convert-source-map": { - "version": "1.9.0", - "dev": true - } - } - }, - "nanoid": { - "version": "3.3.4" - }, - "napi-macros": { - "version": "2.0.0" - }, - "native-abort-controller": { - "version": "1.0.4", - "requires": {} - }, - "native-fetch": { - "version": "3.0.0", - "requires": {} - }, - "natural-compare": { - "version": "1.4.0", - "dev": true - }, - "negotiator": { - "version": "0.6.3", - "dev": true - }, - "neo-async": { - "version": "2.6.2", - "dev": true - }, - "netmask": { - "version": "2.0.2" - }, - "next-tick": { - "version": "1.1.0", - "dev": true - }, - "nise": { - "version": "4.1.0", - "requires": { - "@sinonjs/commons": "^1.7.0", - "@sinonjs/fake-timers": "^6.0.0", - "@sinonjs/text-encoding": "^0.7.1", - "just-extend": "^4.0.2", - "path-to-regexp": "^1.7.0" - } - }, - "no-case": { - "version": "2.3.2", - "dev": true, - "requires": { - "lower-case": "^1.1.1" - } - }, - "noble-ed25519": { - "version": "1.2.6" - }, - "noble-secp256k1": { - "version": "1.2.14" - }, - "node-addon-api": { - "version": "4.3.0", - "dev": true - }, - "node-dir": { - "version": "0.1.17", - "dev": true, - "requires": { - "minimatch": "^3.0.2" - } - }, - "node-fetch": { - "version": "2.6.7", - "requires": { - "whatwg-url": "^5.0.0" - } - }, - "node-forge": { - "version": "0.10.0" - }, - "node-gyp-build": { - "version": "4.5.0" - }, - "node-gyp-build-optional-packages": { - "version": "5.0.3", - "dev": true - }, - "node-preload": { - "version": "0.2.1", - "dev": true, - "requires": { - "process-on-spawn": "^1.0.0" - } - }, - "node-releases": { - "version": "2.0.6", - "dev": true - }, - "normalize-html-whitespace": { - "version": "0.2.0", - "dev": true - }, - "normalize-path": { - "version": "3.0.0", - "dev": true - }, - "npm-run-path": { - "version": "4.0.1", - "requires": { - "path-key": "^3.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "dev": true - }, - "nyc": { - "version": "15.1.0", - "dev": true, - "requires": { - "@istanbuljs/load-nyc-config": "^1.0.0", - "@istanbuljs/schema": "^0.1.2", - "caching-transform": "^4.0.0", - "convert-source-map": "^1.7.0", - "decamelize": "^1.2.0", - "find-cache-dir": "^3.2.0", - "find-up": "^4.1.0", - "foreground-child": "^2.0.0", - "get-package-type": "^0.1.0", - "glob": "^7.1.6", - "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-hook": "^3.0.0", - "istanbul-lib-instrument": "^4.0.0", - "istanbul-lib-processinfo": "^2.0.2", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^4.0.0", - "istanbul-reports": "^3.0.2", - "make-dir": "^3.0.0", - "node-preload": "^0.2.1", - "p-map": "^3.0.0", - "process-on-spawn": "^1.0.0", - "resolve-from": "^5.0.0", - "rimraf": "^3.0.0", - "signal-exit": "^3.0.2", - "spawn-wrap": "^2.0.0", - "test-exclude": "^6.0.0", - "yargs": "^15.0.2" - }, - "dependencies": { - "cliui": { - "version": "6.0.0", - "dev": true, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^6.2.0" - } - }, - "convert-source-map": { - "version": "1.9.0", - "dev": true - }, - "emoji-regex": { - "version": "8.0.0", - "dev": true - }, - "find-up": { - "version": "4.1.0", - "dev": true, - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "dev": true - }, - "locate-path": { - "version": "5.0.0", - "dev": true, - "requires": { - "p-locate": "^4.1.0" - } - }, - "make-dir": { - "version": "3.1.0", - "dev": true, - "requires": { - "semver": "^6.0.0" - } - }, - "p-limit": { - "version": "2.3.0", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "4.1.0", - "dev": true, - "requires": { - "p-limit": "^2.2.0" - } - }, - "p-map": { - "version": "3.0.0", - "dev": true, - "requires": { - "aggregate-error": "^3.0.0" - } - }, - "resolve-from": { - "version": "5.0.0", - "dev": true - }, - "semver": { - "version": "6.3.0", - "dev": true - }, - "string-width": { - "version": "4.2.3", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "wrap-ansi": { - "version": "6.2.0", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - }, - "y18n": { - "version": "4.0.3", - "dev": true - }, - "yargs": { - "version": "15.4.1", - "dev": true, - "requires": { - "cliui": "^6.0.0", - "decamelize": "^1.2.0", - "find-up": "^4.1.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^4.2.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^18.1.2" - } - }, - "yargs-parser": { - "version": "18.1.3", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - } - } - }, - "oauth-sign": { - "version": "0.9.0" - }, - "object-assign": { - "version": "4.1.1" - }, - "object-hash": { - "version": "2.2.0" - }, - "object-inspect": { - "version": "1.12.2" - }, - "object-is": { - "version": "1.1.5", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - } - }, - "object-keys": { - "version": "1.1.1" - }, - "object.assign": { - "version": "4.1.4", - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "has-symbols": "^1.0.3", - "object-keys": "^1.1.1" - } - }, - "object.values": { - "version": "1.1.5", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.1" - } - }, - "on-finished": { - "version": "2.4.1", - "requires": { - "ee-first": "1.1.1" - } - }, - "on-net-listen": { - "version": "1.1.2", - "dev": true - }, - "once": { - "version": "1.4.0", - "dev": true, - "requires": { - "wrappy": "1" - } - }, - "one-time": { - "version": "1.0.0", - "requires": { - "fn.name": "1.x.x" - } - }, - "onetime": { - "version": "5.1.2", - "requires": { - "mimic-fn": "^2.1.0" - } - }, - "opn": { - "version": "5.5.0", - "dev": true, - "requires": { - "is-wsl": "^1.1.0" - }, - "dependencies": { - "is-wsl": { - "version": "1.1.0", - "dev": true - } - } - }, - "optionator": { - "version": "0.9.1", - "dev": true, - "requires": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" - } - }, - "ordered-binary": { - "version": "1.4.0", - "dev": true - }, - "os-browserify": { - "version": "0.3.0", - "dev": true - }, - "os-homedir": { - "version": "1.0.2", - "dev": true - }, - "os-tmpdir": { - "version": "1.0.2", - "dev": true - }, - "p-any": { - "version": "3.0.0", - "requires": { - "p-cancelable": "^2.0.0", - "p-some": "^5.0.0" - } - }, - "p-cancelable": { - "version": "2.1.1" - }, - "p-defer": { - "version": "3.0.0" - }, - "p-fifo": { - "version": "1.0.0", - "requires": { - "fast-fifo": "^1.0.0", - "p-defer": "^3.0.0" - } - }, - "p-filter": { - "version": "2.1.0", - "requires": { - "p-map": "^2.0.0" - }, - "dependencies": { - "p-map": { - "version": "2.1.0" - } - } - }, - "p-finally": { - "version": "1.0.0" - }, - "p-limit": { - "version": "3.1.0", - "requires": { - "yocto-queue": "^0.1.0" - } - }, - "p-locate": { - "version": "5.0.0", - "dev": true, - "requires": { - "p-limit": "^3.0.2" - } - }, - "p-map": { - "version": "4.0.0", - "requires": { - "aggregate-error": "^3.0.0" - } - }, - "p-queue": { - "version": "6.6.2", - "requires": { - "eventemitter3": "^4.0.4", - "p-timeout": "^3.2.0" - }, - "dependencies": { - "p-timeout": { - "version": "3.2.0", - "requires": { - "p-finally": "^1.0.0" - } - } - } - }, - "p-reflect": { - "version": "2.1.0" - }, - "p-retry": { - "version": "4.6.2", - "requires": { - "@types/retry": "0.12.0", - "retry": "^0.13.1" - } - }, - "p-settle": { - "version": "4.1.1", - "requires": { - "p-limit": "^2.2.2", - "p-reflect": "^2.1.0" - }, - "dependencies": { - "p-limit": { - "version": "2.3.0", - "requires": { - "p-try": "^2.0.0" - } - } - } - }, - "p-some": { - "version": "5.0.0", - "requires": { - "aggregate-error": "^3.0.0", - "p-cancelable": "^2.0.0" - } - }, - "p-timeout": { - "version": "4.1.0" - }, - "p-times": { - "version": "3.0.0", - "requires": { - "p-map": "^4.0.0" - } - }, - "p-try": { - "version": "2.2.0" - }, - "p-wait-for": { - "version": "3.2.0", - "requires": { - "p-timeout": "^3.0.0" - }, - "dependencies": { - "p-timeout": { - "version": "3.2.0", - "requires": { - "p-finally": "^1.0.0" - } - } - } - }, - "package-hash": { - "version": "4.0.0", - "dev": true, - "requires": { - "graceful-fs": "^4.1.15", - "hasha": "^5.0.0", - "lodash.flattendeep": "^4.4.0", - "release-zalgo": "^1.0.0" - } - }, - "pad": { - "version": "3.2.0", - "dev": true, - "requires": { - "wcwidth": "^1.0.1" - } - }, - "pako": { - "version": "1.0.11", - "dev": true - }, - "parent-module": { - "version": "1.0.1", - "dev": true, - "requires": { - "callsites": "^3.0.0" - } - }, - "parents": { - "version": "1.0.1", - "dev": true, - "requires": { - "path-platform": "~0.11.15" - } - }, - "parse-asn1": { - "version": "5.1.6", - "dev": true, - "requires": { - "asn1.js": "^5.2.0", - "browserify-aes": "^1.0.0", - "evp_bytestokey": "^1.0.0", - "pbkdf2": "^3.0.3", - "safe-buffer": "^5.1.1" - } - }, - "parse-json": { - "version": "4.0.0", - "dev": true, - "requires": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" - } - }, - "parseurl": { - "version": "1.3.3" - }, - "path-browserify": { - "version": "0.0.1", - "dev": true - }, - "path-exists": { - "version": "4.0.0", - "dev": true - }, - "path-is-absolute": { - "version": "1.0.1", - "dev": true - }, - "path-is-inside": { - "version": "1.0.2", - "dev": true - }, - "path-key": { - "version": "3.1.1" - }, - "path-parse": { - "version": "1.0.7", - "dev": true - }, - "path-platform": { - "version": "0.11.15", - "dev": true - }, - "path-to-regexp": { - "version": "1.8.0", - "requires": { - "isarray": "0.0.1" - }, - "dependencies": { - "isarray": { - "version": "0.0.1" - } - } - }, - "path-type": { - "version": "4.0.0", - "dev": true - }, - "pathval": { - "version": "1.1.1" - }, - "pbkdf2": { - "version": "3.1.2", - "dev": true, - "requires": { - "create-hash": "^1.1.2", - "create-hmac": "^1.1.4", - "ripemd160": "^2.0.1", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - } - }, - "peer-id": { - "version": "0.14.8", - "requires": { - "cids": "^1.1.5", - "class-is": "^1.1.0", - "libp2p-crypto": "^0.19.0", - "minimist": "^1.2.5", - "multihashes": "^4.0.2", - "protobufjs": "^6.10.2", - "uint8arrays": "^2.0.5" - }, - "dependencies": { - "uint8arrays": { - "version": "2.1.10", - "requires": { - "multiformats": "^9.4.2" - } - } - } - }, - "pem-jwk": { - "version": "2.0.0", - "requires": { - "asn1.js": "^5.0.1" - } - }, - "perf-sym": { - "version": "2.0.3", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "minimist": "^1.2.0", - "pump": "^1.0.1", - "resolve-jit-symbols": "^0.5.0", - "split2": "^2.0.1" - }, - "dependencies": { - "pump": { - "version": "1.0.3", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "split2": { - "version": "2.2.0", - "dev": true, - "requires": { - "through2": "^2.0.2" - } - } - } - }, - "performance-now": { - "version": "2.1.0" - }, - "picocolors": { - "version": "1.0.0", - "dev": true - }, - "picomatch": { - "version": "2.3.1", - "dev": true - }, - "pidtree": { - "version": "0.6.0", - "dev": true - }, - "pify": { - "version": "3.0.0", - "dev": true - }, - "pinkie": { - "version": "2.0.4", - "dev": true - }, - "pinkie-promise": { - "version": "2.0.1", - "dev": true, - "requires": { - "pinkie": "^2.0.0" - } - }, - "pino": { - "version": "5.17.0", - "dev": true, - "requires": { - "fast-redact": "^2.0.0", - "fast-safe-stringify": "^2.0.7", - "flatstr": "^1.0.12", - "pino-std-serializers": "^2.4.2", - "quick-format-unescaped": "^3.0.3", - "sonic-boom": "^0.7.5" - } - }, - "pino-std-serializers": { - "version": "2.5.0", - "dev": true - }, - "pkg-conf": { - "version": "2.1.0", - "dev": true, - "requires": { - "find-up": "^2.0.0", - "load-json-file": "^4.0.0" - }, - "dependencies": { - "find-up": { - "version": "2.1.0", - "dev": true, - "requires": { - "locate-path": "^2.0.0" - } - }, - "locate-path": { - "version": "2.0.0", - "dev": true, - "requires": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - } - }, - "p-limit": { - "version": "1.3.0", - "dev": true, - "requires": { - "p-try": "^1.0.0" - } - }, - "p-locate": { - "version": "2.0.0", - "dev": true, - "requires": { - "p-limit": "^1.1.0" - } - }, - "p-try": { - "version": "1.0.0", - "dev": true - }, - "path-exists": { - "version": "3.0.0", - "dev": true - } - } - }, - "pkg-config": { - "version": "1.1.1", - "dev": true, - "requires": { - "debug-log": "^1.0.0", - "find-root": "^1.0.0", - "xtend": "^4.0.1" - } - }, - "pkg-dir": { - "version": "4.2.0", - "dev": true, - "requires": { - "find-up": "^4.0.0" - }, - "dependencies": { - "find-up": { - "version": "4.1.0", - "dev": true, - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "locate-path": { - "version": "5.0.0", - "dev": true, - "requires": { - "p-locate": "^4.1.0" - } - }, - "p-limit": { - "version": "2.3.0", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "4.1.0", - "dev": true, - "requires": { - "p-limit": "^2.2.0" - } - } - } - }, - "pkg-up": { - "version": "1.0.0", - "dev": true, - "requires": { - "find-up": "^1.0.0" - }, - "dependencies": { - "find-up": { - "version": "1.1.2", - "dev": true, - "requires": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, - "path-exists": { - "version": "2.1.0", - "dev": true, - "requires": { - "pinkie-promise": "^2.0.0" - } - } - } - }, - "platform": { - "version": "1.3.6", - "dev": true - }, - "pluralize": { - "version": "1.2.1", - "dev": true - }, - "prelude-ls": { - "version": "1.2.1", - "dev": true - }, - "prettier": { - "version": "2.7.1", - "dev": true - }, - "prettier-linter-helpers": { - "version": "1.0.0", - "dev": true, - "requires": { - "fast-diff": "^1.1.2" - } - }, - "pretty-hrtime": { - "version": "1.0.3", - "dev": true - }, - "pretty-trace": { - "version": "0.3.1", - "dev": true, - "requires": { - "ansicolors": "~0.2.1", - "split2": "~0.2.1" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "dev": true - }, - "readable-stream": { - "version": "1.0.34", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "split2": { - "version": "0.2.1", - "dev": true, - "requires": { - "through2": "~0.6.1" - } - }, - "string_decoder": { - "version": "0.10.31", - "dev": true - }, - "through2": { - "version": "0.6.5", - "dev": true, - "requires": { - "readable-stream": ">=1.0.33-1 <1.1.0-0", - "xtend": ">=4.0.0 <4.1.0-0" - } - } - } - }, - "private-ip": { - "version": "2.3.4", - "requires": { - "ip-regex": "^4.3.0", - "ipaddr.js": "^2.0.1", - "is-ip": "^3.1.0", - "netmask": "^2.0.2" - } - }, - "process": { - "version": "0.11.10", - "dev": true - }, - "process-nextick-args": { - "version": "2.0.1", - "dev": true - }, - "process-on-spawn": { - "version": "1.0.0", - "dev": true, - "requires": { - "fromentries": "^1.2.0" - } - }, - "progress": { - "version": "1.1.8", - "dev": true - }, - "promise-to-callback": { - "version": "1.0.0", - "requires": { - "is-fn": "^1.0.0", - "set-immediate-shim": "^1.0.1" - } - }, - "protobufjs": { - "version": "6.11.3", - "requires": { - "@protobufjs/aspromise": "^1.1.2", - "@protobufjs/base64": "^1.1.2", - "@protobufjs/codegen": "^2.0.4", - "@protobufjs/eventemitter": "^1.1.0", - "@protobufjs/fetch": "^1.1.0", - "@protobufjs/float": "^1.0.2", - "@protobufjs/inquire": "^1.1.0", - "@protobufjs/path": "^1.1.2", - "@protobufjs/pool": "^1.1.0", - "@protobufjs/utf8": "^1.1.0", - "@types/long": "^4.0.1", - "@types/node": ">=13.7.0", - "long": "^4.0.0" - } - }, - "protocol-buffers-schema": { - "version": "3.6.0" - }, - "protons": { - "version": "2.0.3", - "requires": { - "protocol-buffers-schema": "^3.3.1", - "signed-varint": "^2.0.1", - "uint8arrays": "^3.0.0", - "varint": "^5.0.0" - }, - "dependencies": { - "varint": { - "version": "5.0.2" - } - } - }, - "psl": { - "version": "1.9.0" - }, - "public-encrypt": { - "version": "4.0.3", - "dev": true, - "requires": { - "bn.js": "^4.1.0", - "browserify-rsa": "^4.0.0", - "create-hash": "^1.1.0", - "parse-asn1": "^5.0.0", - "randombytes": "^2.0.1", - "safe-buffer": "^5.1.2" - }, - "dependencies": { - "bn.js": { - "version": "4.12.0", - "dev": true - } - } - }, - "pump": { - "version": "3.0.0", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "pumpify": { - "version": "1.5.1", - "dev": true, - "requires": { - "duplexify": "^3.6.0", - "inherits": "^2.0.3", - "pump": "^2.0.0" - }, - "dependencies": { - "pump": { - "version": "2.0.1", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - } - } - }, - "punycode": { - "version": "1.4.1", - "dev": true - }, - "qheap": { - "version": "1.4.0" - }, - "qjobs": { - "version": "1.2.0", - "dev": true - }, - "qs": { - "version": "6.11.0", - "requires": { - "side-channel": "^1.0.4" - } - }, - "querystring": { - "version": "0.2.0", - "dev": true - }, - "querystring-es3": { - "version": "0.2.1", - "dev": true - }, - "queue-microtask": { - "version": "1.2.3" - }, - "queue-tick": { - "version": "1.0.1", - "dev": true - }, - "quibble": { - "version": "0.6.17", - "dev": true, - "requires": { - "lodash": "^4.17.21", - "resolve": "^1.22.1" - } - }, - "quick-format-unescaped": { - "version": "3.0.3", - "dev": true - }, - "randombytes": { - "version": "2.1.0", - "requires": { - "safe-buffer": "^5.1.0" - } - }, - "randomfill": { - "version": "1.0.4", - "dev": true, - "requires": { - "randombytes": "^2.0.5", - "safe-buffer": "^5.1.0" - } - }, - "range-parser": { - "version": "1.2.1", - "dev": true - }, - "raw-body": { - "version": "2.5.1", - "requires": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - } - }, - "react-native-fetch-api": { - "version": "2.0.0", - "requires": { - "p-defer": "^3.0.0" - } - }, - "read-only-stream": { - "version": "2.0.0", - "dev": true, - "requires": { - "readable-stream": "^2.0.2" - } - }, - "readable-stream": { - "version": "2.3.7", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "dev": true - }, - "string_decoder": { - "version": "1.1.1", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "readdirp": { - "version": "3.6.0", - "dev": true, - "requires": { - "picomatch": "^2.2.1" - } - }, - "readline2": { - "version": "1.0.1", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "mute-stream": "0.0.5" - }, - "dependencies": { - "is-fullwidth-code-point": { - "version": "1.0.0", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - } - } - }, - "receptacle": { - "version": "1.3.2", - "requires": { - "ms": "^2.1.1" - }, - "dependencies": { - "ms": { - "version": "2.1.3" - } - } - }, - "rechoir": { - "version": "0.7.1", - "dev": true, - "requires": { - "resolve": "^1.9.0" - } - }, - "regenerate": { - "version": "1.4.2", - "dev": true - }, - "regenerate-unicode-properties": { - "version": "10.1.0", - "dev": true, - "requires": { - "regenerate": "^1.4.2" - } - }, - "regenerator-runtime": { - "version": "0.13.10", - "dev": true - }, - "regenerator-transform": { - "version": "0.15.0", - "dev": true, - "requires": { - "@babel/runtime": "^7.8.4" - } - }, - "regexp.prototype.flags": { - "version": "1.4.3", - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "functions-have-names": "^1.2.2" - } - }, - "regexpp": { - "version": "3.2.0", - "dev": true - }, - "regexpu-core": { - "version": "5.2.1", - "dev": true, - "requires": { - "regenerate": "^1.4.2", - "regenerate-unicode-properties": "^10.1.0", - "regjsgen": "^0.7.1", - "regjsparser": "^0.9.1", - "unicode-match-property-ecmascript": "^2.0.0", - "unicode-match-property-value-ecmascript": "^2.0.0" - } - }, - "regjsgen": { - "version": "0.7.1", - "dev": true - }, - "regjsparser": { - "version": "0.9.1", - "dev": true, - "requires": { - "jsesc": "~0.5.0" - }, - "dependencies": { - "jsesc": { - "version": "0.5.0", - "dev": true - } - } - }, - "release-zalgo": { - "version": "1.0.0", - "dev": true, - "requires": { - "es6-error": "^4.0.1" - } - }, - "request": { - "version": "2.88.2", - "requires": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.3", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.5.0", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - }, - "dependencies": { - "qs": { - "version": "6.5.3" - }, - "uuid": { - "version": "3.4.0" - } - } - }, - "require-directory": { - "version": "2.1.1" - }, - "require-main-filename": { - "version": "2.0.0", - "dev": true - }, - "require-uncached": { - "version": "1.0.3", - "dev": true, - "requires": { - "caller-path": "^0.1.0", - "resolve-from": "^1.0.0" - }, - "dependencies": { - "resolve-from": { - "version": "1.0.1", - "dev": true - } - } - }, - "requires-port": { - "version": "1.0.0", - "dev": true - }, - "resolve": { - "version": "1.22.1", - "dev": true, - "requires": { - "is-core-module": "^2.9.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - } - }, - "resolve-cwd": { - "version": "3.0.0", - "dev": true, - "requires": { - "resolve-from": "^5.0.0" - }, - "dependencies": { - "resolve-from": { - "version": "5.0.0", - "dev": true - } - } - }, - "resolve-from": { - "version": "4.0.0", - "dev": true - }, - "resolve-jit-symbols": { - "version": "0.5.0", - "dev": true, - "requires": { - "pretty-trace": "~0.3.1" - } - }, - "restore-cursor": { - "version": "3.1.0", - "dev": true, - "requires": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - } - }, - "resumer": { - "version": "0.0.0", - "dev": true, - "requires": { - "through": "~2.3.4" - } - }, - "retimer": { - "version": "2.0.0" - }, - "retry": { - "version": "0.13.1" - }, - "reusify": { - "version": "1.0.4", - "dev": true - }, - "rfdc": { - "version": "1.3.0", - "dev": true - }, - "rimraf": { - "version": "3.0.2", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "ripemd160": { - "version": "2.0.2", - "dev": true, - "requires": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1" - } - }, - "run-async": { - "version": "0.1.0", - "dev": true, - "requires": { - "once": "^1.3.0" - } - }, - "run-parallel": { - "version": "1.2.0", - "dev": true, - "requires": { - "queue-microtask": "^1.2.2" - } - }, - "run-parallel-limit": { - "version": "1.1.0", - "requires": { - "queue-microtask": "^1.2.2" - } - }, - "rustbn.js": { - "version": "0.2.0" - }, - "rx-lite": { - "version": "3.1.2", - "dev": true - }, - "rxjs": { - "version": "7.5.7", - "dev": true, - "requires": { - "tslib": "^2.1.0" - } - }, - "safe-buffer": { - "version": "5.2.1" - }, - "safe-regex-test": { - "version": "1.0.0", - "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", - "is-regex": "^1.1.4" - } - }, - "safe-stable-stringify": { - "version": "2.4.1" - }, - "safer-buffer": { - "version": "2.1.2" - }, - "sanitize-filename": { - "version": "1.6.3", - "requires": { - "truncate-utf8-bytes": "^1.0.0" - } - }, - "sax": { - "version": "1.2.4" - }, - "scanf": { - "version": "1.1.2" - }, - "schema-utils": { - "version": "2.7.1", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.5", - "ajv": "^6.12.4", - "ajv-keywords": "^3.5.2" - } - }, - "scrypt-js": { - "version": "3.0.1" - }, - "secp256k1": { - "version": "4.0.3", - "requires": { - "elliptic": "^6.5.4", - "node-addon-api": "^2.0.0", - "node-gyp-build": "^4.2.0" - }, - "dependencies": { - "node-addon-api": { - "version": "2.0.2" - } - } - }, - "semver": { - "version": "7.3.8", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - }, - "dependencies": { - "lru-cache": { - "version": "6.0.0", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, - "yallist": { - "version": "4.0.0", - "dev": true - } - } - }, - "serialize-javascript": { - "version": "6.0.0", - "dev": true, - "requires": { - "randombytes": "^2.1.0" - } - }, - "set-blocking": { - "version": "2.0.0", - "dev": true - }, - "set-delayed-interval": { - "version": "1.0.0" - }, - "set-immediate-shim": { - "version": "1.0.1" - }, - "setimmediate": { - "version": "1.0.5", - "dev": true - }, - "setprototypeof": { - "version": "1.2.0" - }, - "sha.js": { - "version": "2.4.11", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "shallow-clone": { - "version": "3.0.1", - "dev": true, - "requires": { - "kind-of": "^6.0.2" - } - }, - "shasum": { - "version": "1.0.2", - "dev": true, - "requires": { - "json-stable-stringify": "~0.0.0", - "sha.js": "~2.4.4" - } - }, - "shasum-object": { - "version": "1.0.0", - "dev": true, - "requires": { - "fast-safe-stringify": "^2.0.7" - } - }, - "shebang-command": { - "version": "2.0.0", - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0" - }, - "shell-quote": { - "version": "1.7.4", - "dev": true - }, - "shelljs": { - "version": "0.7.8", - "dev": true, - "requires": { - "glob": "^7.0.0", - "interpret": "^1.0.0", - "rechoir": "^0.6.2" - }, - "dependencies": { - "interpret": { - "version": "1.4.0", - "dev": true - }, - "rechoir": { - "version": "0.6.2", - "dev": true, - "requires": { - "resolve": "^1.1.6" - } - } - } - }, - "shiki": { - "version": "0.10.1", - "dev": true, - "requires": { - "jsonc-parser": "^3.0.0", - "vscode-oniguruma": "^1.6.1", - "vscode-textmate": "5.2.0" - } - }, - "side-channel": { - "version": "1.0.4", - "requires": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - } - }, - "signal-exit": { - "version": "3.0.7" - }, - "signed-varint": { - "version": "2.0.1", - "requires": { - "varint": "~5.0.0" - }, - "dependencies": { - "varint": { - "version": "5.0.2" - } - } - }, - "simple-concat": { - "version": "1.0.1", - "dev": true - }, - "simple-swizzle": { - "version": "0.2.2", - "requires": { - "is-arrayish": "^0.3.1" - }, - "dependencies": { - "is-arrayish": { - "version": "0.3.2" - } - } - }, - "single-line-log": { - "version": "1.1.2", - "dev": true, - "requires": { - "string-width": "^1.0.1" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "string-width": { - "version": "1.0.2", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - } - } - }, - "sinon": { - "version": "9.2.4", - "requires": { - "@sinonjs/commons": "^1.8.1", - "@sinonjs/fake-timers": "^6.0.1", - "@sinonjs/samsam": "^5.3.1", - "diff": "^4.0.2", - "nise": "^4.0.4", - "supports-color": "^7.1.0" - } - }, - "slash": { - "version": "3.0.0", - "dev": true - }, - "slice-ansi": { - "version": "5.0.0", - "dev": true, - "requires": { - "ansi-styles": "^6.0.0", - "is-fullwidth-code-point": "^4.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "6.2.1", - "dev": true - } - } - }, - "snappyjs": { - "version": "0.6.1" - }, - "socket.io": { - "version": "4.5.3", - "dev": true, - "requires": { - "accepts": "~1.3.4", - "base64id": "~2.0.0", - "debug": "~4.3.2", - "engine.io": "~6.2.0", - "socket.io-adapter": "~2.4.0", - "socket.io-parser": "~4.2.0" - } - }, - "socket.io-adapter": { - "version": "2.4.0", - "dev": true - }, - "socket.io-parser": { - "version": "4.2.1", - "dev": true, - "requires": { - "@socket.io/component-emitter": "~3.1.0", - "debug": "~4.3.1" - } - }, - "solc": { - "version": "0.8.17", - "dev": true, - "requires": { - "command-exists": "^1.2.8", - "commander": "^8.1.0", - "follow-redirects": "^1.12.1", - "js-sha3": "0.8.0", - "memorystream": "^0.3.1", - "semver": "^5.5.0", - "tmp": "0.0.33" - }, - "dependencies": { - "commander": { - "version": "8.3.0", - "dev": true - }, - "semver": { - "version": "5.7.1", - "dev": true - }, - "tmp": { - "version": "0.0.33", - "dev": true, - "requires": { - "os-tmpdir": "~1.0.2" - } - } - } - }, - "sonic-boom": { - "version": "0.7.7", - "dev": true, - "requires": { - "atomic-sleep": "^1.0.0", - "flatstr": "^1.0.12" - } - }, - "sort-object-keys": { - "version": "1.1.3", - "dev": true - }, - "sort-package-json": { - "version": "1.57.0", - "dev": true, - "requires": { - "detect-indent": "^6.0.0", - "detect-newline": "3.1.0", - "git-hooks-list": "1.0.3", - "globby": "10.0.0", - "is-plain-obj": "2.1.0", - "sort-object-keys": "^1.1.3" - }, - "dependencies": { - "globby": { - "version": "10.0.0", - "dev": true, - "requires": { - "@types/glob": "^7.1.1", - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.0.3", - "glob": "^7.1.3", - "ignore": "^5.1.1", - "merge2": "^1.2.3", - "slash": "^3.0.0" - } - } - } - }, - "source-map": { - "version": "0.5.7", - "dev": true - }, - "source-map-support": { - "version": "0.5.21", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "dev": true - } - } - }, - "sourcemap-codec": { - "version": "1.4.8", - "dev": true - }, - "spawn-wrap": { - "version": "2.0.0", - "dev": true, - "requires": { - "foreground-child": "^2.0.0", - "is-windows": "^1.0.2", - "make-dir": "^3.0.0", - "rimraf": "^3.0.0", - "signal-exit": "^3.0.2", - "which": "^2.0.1" - }, - "dependencies": { - "make-dir": { - "version": "3.1.0", - "dev": true, - "requires": { - "semver": "^6.0.0" - } - }, - "semver": { - "version": "6.3.0", - "dev": true - }, - "which": { - "version": "2.0.2", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - } - } - }, - "split2": { - "version": "3.2.2", - "dev": true, - "requires": { - "readable-stream": "^3.0.0" - }, - "dependencies": { - "readable-stream": { - "version": "3.6.0", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } - } - }, - "sprintf-js": { - "version": "1.1.2" - }, - "sshpk": { - "version": "1.17.0", - "requires": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - }, - "dependencies": { - "jsbn": { - "version": "0.1.1" - } - } - }, - "stack-trace": { - "version": "0.0.10" - }, - "standard": { - "version": "10.0.3", - "dev": true, - "requires": { - "eslint": "~3.19.0", - "eslint-config-standard": "10.2.1", - "eslint-config-standard-jsx": "4.0.2", - "eslint-plugin-import": "~2.2.0", - "eslint-plugin-node": "~4.2.2", - "eslint-plugin-promise": "~3.5.0", - "eslint-plugin-react": "~6.10.0", - "eslint-plugin-standard": "~3.0.1", - "standard-engine": "~7.0.0" - }, - "dependencies": { - "acorn": { - "version": "5.7.4", - "dev": true - }, - "acorn-jsx": { - "version": "3.0.1", - "dev": true, - "requires": { - "acorn": "^3.0.4" - }, - "dependencies": { - "acorn": { - "version": "3.3.0", - "dev": true - } - } - }, - "ansi-regex": { - "version": "2.1.1", - "dev": true - }, - "ansi-styles": { - "version": "2.2.1", - "dev": true - }, - "argparse": { - "version": "1.0.10", - "dev": true, - "requires": { - "sprintf-js": "~1.0.2" - } - }, - "chalk": { - "version": "1.1.3", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } - }, - "debug": { - "version": "2.6.9", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "doctrine": { - "version": "2.1.0", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - }, - "eslint": { - "version": "3.19.0", - "dev": true, - "requires": { - "babel-code-frame": "^6.16.0", - "chalk": "^1.1.3", - "concat-stream": "^1.5.2", - "debug": "^2.1.1", - "doctrine": "^2.0.0", - "escope": "^3.6.0", - "espree": "^3.4.0", - "esquery": "^1.0.0", - "estraverse": "^4.2.0", - "esutils": "^2.0.2", - "file-entry-cache": "^2.0.0", - "glob": "^7.0.3", - "globals": "^9.14.0", - "ignore": "^3.2.0", - "imurmurhash": "^0.1.4", - "inquirer": "^0.12.0", - "is-my-json-valid": "^2.10.0", - "is-resolvable": "^1.0.0", - "js-yaml": "^3.5.1", - "json-stable-stringify": "^1.0.0", - "levn": "^0.3.0", - "lodash": "^4.0.0", - "mkdirp": "^0.5.0", - "natural-compare": "^1.4.0", - "optionator": "^0.8.2", - "path-is-inside": "^1.0.1", - "pluralize": "^1.2.1", - "progress": "^1.1.8", - "require-uncached": "^1.0.2", - "shelljs": "^0.7.5", - "strip-bom": "^3.0.0", - "strip-json-comments": "~2.0.1", - "table": "^3.7.8", - "text-table": "~0.2.0", - "user-home": "^2.0.0" - } - }, - "eslint-config-standard-jsx": { - "version": "4.0.2", - "dev": true, - "requires": {} - }, - "eslint-import-resolver-node": { - "version": "0.2.3", - "dev": true, - "requires": { - "debug": "^2.2.0", - "object-assign": "^4.0.1", - "resolve": "^1.1.6" - } - }, - "eslint-plugin-import": { - "version": "2.2.0", - "dev": true, - "requires": { - "builtin-modules": "^1.1.1", - "contains-path": "^0.1.0", - "debug": "^2.2.0", - "doctrine": "1.5.0", - "eslint-import-resolver-node": "^0.2.0", - "eslint-module-utils": "^2.0.0", - "has": "^1.0.1", - "lodash.cond": "^4.3.0", - "minimatch": "^3.0.3", - "pkg-up": "^1.0.0" - }, - "dependencies": { - "doctrine": { - "version": "1.5.0", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "isarray": "^1.0.0" - } - } - } - }, - "eslint-plugin-react": { - "version": "6.10.3", - "dev": true, - "requires": { - "array.prototype.find": "^2.0.1", - "doctrine": "^1.2.2", - "has": "^1.0.1", - "jsx-ast-utils": "^1.3.4", - "object.assign": "^4.0.4" - }, - "dependencies": { - "doctrine": { - "version": "1.5.0", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "isarray": "^1.0.0" - } - } - } - }, - "espree": { - "version": "3.5.4", - "dev": true, - "requires": { - "acorn": "^5.5.0", - "acorn-jsx": "^3.0.0" - } - }, - "file-entry-cache": { - "version": "2.0.0", - "dev": true, - "requires": { - "flat-cache": "^1.2.1", - "object-assign": "^4.0.1" - } - }, - "flat-cache": { - "version": "1.3.4", - "dev": true, - "requires": { - "circular-json": "^0.3.1", - "graceful-fs": "^4.1.2", - "rimraf": "~2.6.2", - "write": "^0.2.1" - } - }, - "globals": { - "version": "9.18.0", - "dev": true - }, - "ignore": { - "version": "3.3.10", - "dev": true - }, - "js-yaml": { - "version": "3.14.1", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - }, - "json-stable-stringify": { - "version": "1.0.1", - "dev": true, - "requires": { - "jsonify": "~0.0.0" - } - }, - "jsx-ast-utils": { - "version": "1.4.1", - "dev": true - }, - "levn": { - "version": "0.3.0", - "dev": true, - "requires": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - } - }, - "ms": { - "version": "2.0.0", - "dev": true - }, - "optionator": { - "version": "0.8.3", - "dev": true, - "requires": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.6", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "word-wrap": "~1.2.3" - } - }, - "prelude-ls": { - "version": "1.1.2", - "dev": true - }, - "rimraf": { - "version": "2.6.3", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "sprintf-js": { - "version": "1.0.3", - "dev": true - }, - "strip-ansi": { - "version": "3.0.1", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "strip-bom": { - "version": "3.0.0", - "dev": true - }, - "strip-json-comments": { - "version": "2.0.1", - "dev": true - }, - "supports-color": { - "version": "2.0.0", - "dev": true - }, - "type-check": { - "version": "0.3.2", - "dev": true, - "requires": { - "prelude-ls": "~1.1.2" - } - } - } - }, - "standard-engine": { - "version": "7.0.0", - "dev": true, - "requires": { - "deglob": "^2.1.0", - "get-stdin": "^5.0.1", - "minimist": "^1.1.0", - "pkg-conf": "^2.0.0" - } - }, - "statuses": { - "version": "1.5.0" - }, - "stream-browserify": { - "version": "3.0.0", - "dev": true, - "requires": { - "inherits": "~2.0.4", - "readable-stream": "^3.5.0" - }, - "dependencies": { - "readable-stream": { - "version": "3.6.0", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } - } - }, - "stream-combiner2": { - "version": "1.1.1", - "dev": true, - "requires": { - "duplexer2": "~0.1.0", - "readable-stream": "^2.0.2" - } - }, - "stream-http": { - "version": "3.2.0", - "dev": true, - "requires": { - "builtin-status-codes": "^3.0.0", - "inherits": "^2.0.4", - "readable-stream": "^3.6.0", - "xtend": "^4.0.2" - }, - "dependencies": { - "readable-stream": { - "version": "3.6.0", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } - } - }, - "stream-shift": { - "version": "1.0.1", - "dev": true - }, - "stream-splicer": { - "version": "2.0.1", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "readable-stream": "^2.0.2" - } - }, - "stream-to-it": { - "version": "0.2.4", - "requires": { - "get-iterator": "^1.0.2" - } - }, - "streaming-iterables": { - "version": "5.0.4" - }, - "streamroller": { - "version": "3.1.3", - "dev": true, - "requires": { - "date-format": "^4.0.14", - "debug": "^4.3.4", - "fs-extra": "^8.1.0" - }, - "dependencies": { - "fs-extra": { - "version": "8.1.0", - "dev": true, - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, - "jsonfile": { - "version": "4.0.0", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6" - } - }, - "universalify": { - "version": "0.1.2", - "dev": true - } - } - }, - "string_decoder": { - "version": "1.3.0", - "requires": { - "safe-buffer": "~5.2.0" - } - }, - "string-argv": { - "version": "0.3.1", - "dev": true - }, - "string-width": { - "version": "5.1.2", - "dev": true, - "requires": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "dependencies": { - "ansi-regex": { - "version": "6.0.1", - "dev": true - }, - "strip-ansi": { - "version": "7.0.1", - "dev": true, - "requires": { - "ansi-regex": "^6.0.1" - } - } - } - }, - "string.prototype.trim": { - "version": "1.2.6", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.19.5" - } - }, - "string.prototype.trimend": { - "version": "1.0.5", - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.19.5" - } - }, - "string.prototype.trimstart": { - "version": "1.0.5", - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.19.5" - } - }, - "stringify-object-es5": { - "version": "2.5.0", - "dev": true, - "requires": { - "is-plain-obj": "^1.0.0", - "is-regexp": "^1.0.0" - }, - "dependencies": { - "is-plain-obj": { - "version": "1.1.0", - "dev": true - } - } - }, - "strip-ansi": { - "version": "6.0.1", - "requires": { - "ansi-regex": "^5.0.1" - } - }, - "strip-bom": { - "version": "4.0.0", - "dev": true - }, - "strip-final-newline": { - "version": "2.0.0" - }, - "strip-json-comments": { - "version": "3.1.1", - "dev": true - }, - "subarg": { - "version": "1.0.0", - "dev": true, - "requires": { - "minimist": "^1.1.0" - } - }, - "superagent": { - "version": "8.0.2", - "dev": true, - "requires": { - "component-emitter": "^1.3.0", - "cookiejar": "^2.1.3", - "debug": "^4.3.4", - "fast-safe-stringify": "^2.1.1", - "form-data": "^4.0.0", - "formidable": "^2.0.1", - "methods": "^1.1.2", - "mime": "2.6.0", - "qs": "^6.11.0", - "semver": "^7.3.7" - }, - "dependencies": { - "form-data": { - "version": "4.0.0", - "dev": true, - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - } - } - } - }, - "supertest": { - "version": "6.3.0", - "dev": true, - "requires": { - "methods": "^1.1.2", - "superagent": "^8.0.0" - } - }, - "superwstest": { - "version": "2.0.3", - "dev": true, - "requires": { - "@types/supertest": "<7", - "@types/ws": "7.x || 8.x", - "ws": "7.x || 8.x" - } - }, - "supports-color": { - "version": "7.2.0", - "requires": { - "has-flag": "^4.0.0" - } - }, - "supports-preserve-symlinks-flag": { - "version": "1.0.0", - "dev": true - }, - "svg-element-attributes": { - "version": "1.3.1", - "dev": true - }, - "syntax-error": { - "version": "1.4.0", - "dev": true, - "requires": { - "acorn-node": "^1.2.0" - } - }, - "table": { - "version": "3.8.3", - "dev": true, - "requires": { - "ajv": "^4.7.0", - "ajv-keywords": "^1.0.0", - "chalk": "^1.1.1", - "lodash": "^4.0.0", - "slice-ansi": "0.0.4", - "string-width": "^2.0.0" - }, - "dependencies": { - "ajv": { - "version": "4.11.8", - "dev": true, - "requires": { - "co": "^4.6.0", - "json-stable-stringify": "^1.0.1" - } - }, - "ajv-keywords": { - "version": "1.5.1", - "dev": true, - "requires": {} - }, - "ansi-regex": { - "version": "2.1.1", - "dev": true - }, - "ansi-styles": { - "version": "2.2.1", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "dev": true - }, - "json-stable-stringify": { - "version": "1.0.1", - "dev": true, - "requires": { - "jsonify": "~0.0.0" - } - }, - "slice-ansi": { - "version": "0.0.4", - "dev": true - }, - "string-width": { - "version": "2.1.1", - "dev": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.1", - "dev": true - }, - "strip-ansi": { - "version": "4.0.0", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - } - } - }, - "strip-ansi": { - "version": "3.0.1", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "supports-color": { - "version": "2.0.0", - "dev": true - } - } - }, - "tachyons": { - "version": "4.12.0", - "dev": true - }, - "tapable": { - "version": "2.2.1", - "dev": true - }, - "tape": { - "version": "5.6.0", - "dev": true, - "requires": { - "array.prototype.every": "^1.1.3", - "call-bind": "^1.0.2", - "deep-equal": "^2.0.5", - "defined": "^1.0.0", - "dotignore": "^0.1.2", - "for-each": "^0.3.3", - "get-package-type": "^0.1.0", - "glob": "^7.2.3", - "has": "^1.0.3", - "has-dynamic-import": "^2.0.1", - "inherits": "^2.0.4", - "is-regex": "^1.1.4", - "minimist": "^1.2.6", - "object-inspect": "^1.12.2", - "object-is": "^1.1.5", - "object-keys": "^1.1.1", - "object.assign": "^4.1.3", - "resolve": "^2.0.0-next.3", - "resumer": "^0.0.0", - "string.prototype.trim": "^1.2.6", - "through": "^2.3.8" - }, - "dependencies": { - "resolve": { - "version": "2.0.0-next.4", - "dev": true, - "requires": { - "is-core-module": "^2.9.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - } - } - } - }, - "terser": { - "version": "5.15.1", - "dev": true, - "requires": { - "@jridgewell/source-map": "^0.3.2", - "acorn": "^8.5.0", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - }, - "dependencies": { - "commander": { - "version": "2.20.3", - "dev": true - } - } - }, - "terser-webpack-plugin": { - "version": "5.3.6", - "dev": true, - "requires": { - "@jridgewell/trace-mapping": "^0.3.14", - "jest-worker": "^27.4.5", - "schema-utils": "^3.1.1", - "serialize-javascript": "^6.0.0", - "terser": "^5.14.1" - }, - "dependencies": { - "schema-utils": { - "version": "3.1.1", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - } - } - } - }, - "test-exclude": { - "version": "6.0.0", - "dev": true, - "requires": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" - } - }, - "testdouble": { - "version": "3.17.2", - "dev": true, - "requires": { - "lodash": "^4.17.21", - "quibble": "^0.6.17", - "stringify-object-es5": "^2.5.0", - "theredoc": "^1.0.0" - } - }, - "testdouble-timers": { - "version": "0.1.1", - "dev": true, - "requires": { - "lolex": "^1.4.0" - } - }, - "text-hex": { - "version": "1.0.0" - }, - "text-table": { - "version": "0.2.0", - "dev": true - }, - "theredoc": { - "version": "1.0.0", - "dev": true - }, - "through": { - "version": "2.3.8" - }, - "through2": { - "version": "2.0.5", - "dev": true, - "requires": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } - }, - "timeout-abort-controller": { - "version": "1.1.1", - "requires": { - "abort-controller": "^3.0.0", - "retimer": "^2.0.0" - } - }, - "timers-browserify": { - "version": "1.4.2", - "dev": true, - "requires": { - "process": "~0.11.0" - } - }, - "tmp": { - "version": "0.2.1", - "dev": true, - "requires": { - "rimraf": "^3.0.0" - } - }, - "to-fast-properties": { - "version": "2.0.0", - "dev": true - }, - "to-regex-range": { - "version": "5.0.1", - "dev": true, - "requires": { - "is-number": "^7.0.0" - } - }, - "toidentifier": { - "version": "1.0.1" - }, - "tough-cookie": { - "version": "2.5.0", - "requires": { - "psl": "^1.1.28", - "punycode": "^2.1.1" - }, - "dependencies": { - "punycode": { - "version": "2.1.1" - } - } - }, - "tr46": { - "version": "0.0.3" - }, - "transform-ast": { - "version": "2.4.4", - "dev": true, - "requires": { - "acorn-node": "^1.3.0", - "convert-source-map": "^1.5.1", - "dash-ast": "^1.0.0", - "is-buffer": "^2.0.0", - "magic-string": "^0.23.2", - "merge-source-map": "1.0.4", - "nanobench": "^2.1.1" - }, - "dependencies": { - "convert-source-map": { - "version": "1.9.0", - "dev": true - }, - "magic-string": { - "version": "0.23.2", - "dev": true, - "requires": { - "sourcemap-codec": "^1.4.1" - } - } - } - }, - "triple-beam": { - "version": "1.3.0" - }, - "truncate-utf8-bytes": { - "version": "1.0.2", - "requires": { - "utf8-byte-length": "^1.0.1" - } - }, - "ts-node": { - "version": "10.9.1", - "dev": true, - "requires": { - "@cspotcode/source-map-support": "^0.8.0", - "@tsconfig/node10": "^1.0.7", - "@tsconfig/node12": "^1.0.7", - "@tsconfig/node14": "^1.0.0", - "@tsconfig/node16": "^1.0.2", - "acorn": "^8.4.1", - "acorn-walk": "^8.1.1", - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.1", - "yn": "3.1.1" - }, - "dependencies": { - "acorn-walk": { - "version": "8.2.0", - "dev": true - } - } - }, - "tsconfig-paths": { - "version": "3.14.1", - "dev": true, - "requires": { - "@types/json5": "^0.0.29", - "json5": "^1.0.1", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" - }, - "dependencies": { - "json5": { - "version": "1.0.1", - "dev": true, - "requires": { - "minimist": "^1.2.0" - } - }, - "strip-bom": { - "version": "3.0.0", - "dev": true - } - } - }, - "tslib": { - "version": "2.4.0", - "dev": true - }, - "tsutils": { - "version": "3.21.0", - "dev": true, - "requires": { - "tslib": "^1.8.1" - }, - "dependencies": { - "tslib": { - "version": "1.14.1", - "dev": true - } - } - }, - "tty-browserify": { - "version": "0.0.1", - "dev": true - }, - "tunnel-agent": { - "version": "0.6.0", - "requires": { - "safe-buffer": "^5.0.1" - } - }, - "tweetnacl": { - "version": "0.14.5" - }, - "type": { - "version": "1.2.0", - "dev": true - }, - "type-check": { - "version": "0.4.0", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1" - } - }, - "type-component": { - "version": "0.0.1", - "dev": true - }, - "type-detect": { - "version": "4.0.8" - }, - "type-fest": { - "version": "0.20.2", - "dev": true - }, - "type-is": { - "version": "1.6.18", - "requires": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - } - }, - "typedarray": { - "version": "0.0.6", - "dev": true - }, - "typedarray-to-buffer": { - "version": "3.1.5", - "dev": true, - "requires": { - "is-typedarray": "^1.0.0" - } - }, - "typedoc": { - "version": "0.23.10", - "dev": true, - "requires": { - "lunr": "^2.3.9", - "marked": "^4.0.18", - "minimatch": "^5.1.0", - "shiki": "^0.10.1" - }, - "dependencies": { - "brace-expansion": { - "version": "2.0.1", - "dev": true, - "requires": { - "balanced-match": "^1.0.0" - } - }, - "minimatch": { - "version": "5.1.0", - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - } - } - }, - "typedoc-plugin-markdown": { - "version": "3.13.4", - "dev": true, - "requires": { - "handlebars": "^4.7.7" - } - }, - "typescript": { - "version": "4.7.4", - "dev": true - }, - "ua-parser-js": { - "version": "0.7.32", - "dev": true - }, - "uglify-js": { - "version": "3.17.3", - "dev": true, - "optional": true - }, - "uint8arrays": { - "version": "3.1.1", - "requires": { - "multiformats": "^9.4.2" - } - }, - "umd": { - "version": "3.0.3", - "dev": true - }, - "unbox-primitive": { - "version": "1.0.2", - "requires": { - "call-bind": "^1.0.2", - "has-bigints": "^1.0.2", - "has-symbols": "^1.0.3", - "which-boxed-primitive": "^1.0.2" - } - }, - "undeclared-identifiers": { - "version": "1.1.3", - "dev": true, - "requires": { - "acorn-node": "^1.3.0", - "dash-ast": "^1.0.0", - "get-assigned-identifiers": "^1.2.0", - "simple-concat": "^1.0.0", - "xtend": "^4.0.1" - } - }, - "unicode-canonical-property-names-ecmascript": { - "version": "2.0.0", - "dev": true - }, - "unicode-match-property-ecmascript": { - "version": "2.0.0", - "dev": true, - "requires": { - "unicode-canonical-property-names-ecmascript": "^2.0.0", - "unicode-property-aliases-ecmascript": "^2.0.0" - } - }, - "unicode-match-property-value-ecmascript": { - "version": "2.0.0", - "dev": true - }, - "unicode-property-aliases-ecmascript": { - "version": "2.1.0", - "dev": true - }, - "uniq": { - "version": "1.0.1", - "dev": true - }, - "universalify": { - "version": "2.0.0" - }, - "unordered-array-remove": { - "version": "1.0.2" - }, - "unpipe": { - "version": "1.0.0" - }, - "update-browserslist-db": { - "version": "1.0.10", - "dev": true, - "requires": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" - } - }, - "upper-case": { - "version": "1.1.3", - "dev": true - }, - "uri-js": { - "version": "4.4.1", - "requires": { - "punycode": "^2.1.0" - }, - "dependencies": { - "punycode": { - "version": "2.1.1" - } - } - }, - "url": { - "version": "0.11.0", - "dev": true, - "requires": { - "punycode": "1.3.2", - "querystring": "0.2.0" - }, - "dependencies": { - "punycode": { - "version": "1.3.2", - "dev": true - } - } - }, - "ursa-optional": { - "version": "0.10.2", - "requires": { - "bindings": "^1.5.0", - "nan": "^2.14.2" - } - }, - "user-home": { - "version": "2.0.0", - "dev": true, - "requires": { - "os-homedir": "^1.0.0" - } - }, - "utf8-byte-length": { - "version": "1.0.4" - }, - "util": { - "version": "0.12.5", - "requires": { - "inherits": "^2.0.3", - "is-arguments": "^1.0.4", - "is-generator-function": "^1.0.7", - "is-typed-array": "^1.1.3", - "which-typed-array": "^1.1.2" - } - }, - "util-deprecate": { - "version": "1.0.2" - }, - "util-extend": { - "version": "1.0.3", - "dev": true - }, - "utils-merge": { - "version": "1.0.1" - }, - "uuid": { - "version": "8.3.2" - }, - "v8-compile-cache": { - "version": "2.3.0", - "dev": true - }, - "v8-compile-cache-lib": { - "version": "3.0.1", - "dev": true - }, - "v8-to-istanbul": { - "version": "9.0.1", - "dev": true, - "requires": { - "@jridgewell/trace-mapping": "^0.3.12", - "@types/istanbul-lib-coverage": "^2.0.1", - "convert-source-map": "^1.6.0" - }, - "dependencies": { - "convert-source-map": { - "version": "1.9.0", - "dev": true - } - } - }, - "varint": { - "version": "6.0.0" - }, - "vary": { - "version": "1.1.2" - }, - "verror": { - "version": "1.10.0", - "requires": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - }, - "dependencies": { - "core-util-is": { - "version": "1.0.2" - } - } - }, - "vm-browserify": { - "version": "1.1.2", - "dev": true - }, - "void-elements": { - "version": "2.0.1", - "dev": true - }, - "vscode-oniguruma": { - "version": "1.6.2", - "dev": true - }, - "vscode-textmate": { - "version": "5.2.0", - "dev": true - }, - "watchpack": { - "version": "2.4.0", - "dev": true, - "requires": { - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.1.2" - } - }, - "wcwidth": { - "version": "1.0.1", - "dev": true, - "requires": { - "defaults": "^1.0.3" - } - }, - "weak-lru-cache": { - "version": "1.2.2", - "dev": true - }, - "web-encoding": { - "version": "1.1.5", - "requires": { - "@zxing/text-encoding": "0.9.0", - "util": "^0.12.3" - } - }, - "webidl-conversions": { - "version": "3.0.1" - }, - "webpack": { - "version": "5.74.0", - "dev": true, - "requires": { - "@types/eslint-scope": "^3.7.3", - "@types/estree": "^0.0.51", - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/wasm-edit": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1", - "acorn": "^8.7.1", - "acorn-import-assertions": "^1.7.6", - "browserslist": "^4.14.5", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.10.0", - "es-module-lexer": "^0.9.0", - "eslint-scope": "5.1.1", - "events": "^3.2.0", - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.9", - "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.2.0", - "mime-types": "^2.1.27", - "neo-async": "^2.6.2", - "schema-utils": "^3.1.0", - "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.1.3", - "watchpack": "^2.4.0", - "webpack-sources": "^3.2.3" - }, - "dependencies": { - "events": { - "version": "3.3.0", - "dev": true - }, - "schema-utils": { - "version": "3.1.1", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - } - } - } - }, - "webpack-cli": { - "version": "4.10.0", - "dev": true, - "requires": { - "@discoveryjs/json-ext": "^0.5.0", - "@webpack-cli/configtest": "^1.2.0", - "@webpack-cli/info": "^1.5.0", - "@webpack-cli/serve": "^1.7.0", - "colorette": "^2.0.14", - "commander": "^7.0.0", - "cross-spawn": "^7.0.3", - "fastest-levenshtein": "^1.0.12", - "import-local": "^3.0.2", - "interpret": "^2.2.0", - "rechoir": "^0.7.0", - "webpack-merge": "^5.7.3" - }, - "dependencies": { - "commander": { - "version": "7.2.0", - "dev": true - } - } - }, - "webpack-merge": { - "version": "5.8.0", - "dev": true, - "requires": { - "clone-deep": "^4.0.1", - "wildcard": "^2.0.0" - } - }, - "webpack-sources": { - "version": "3.2.3", - "dev": true - }, - "whatwg-url": { - "version": "5.0.0", - "requires": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "which": { - "version": "1.3.1", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "which-boxed-primitive": { - "version": "1.0.2", - "requires": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" - } - }, - "which-collection": { - "version": "1.0.1", - "dev": true, - "requires": { - "is-map": "^2.0.1", - "is-set": "^2.0.1", - "is-weakmap": "^2.0.1", - "is-weakset": "^2.0.1" - } - }, - "which-module": { - "version": "2.0.0", - "dev": true - }, - "which-typed-array": { - "version": "1.1.8", - "requires": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "es-abstract": "^1.20.0", - "for-each": "^0.3.3", - "has-tostringtag": "^1.0.0", - "is-typed-array": "^1.1.9" - } - }, - "wildcard": { - "version": "2.0.0", - "dev": true - }, - "winston": { - "version": "3.8.2", - "requires": { - "@colors/colors": "1.5.0", - "@dabh/diagnostics": "^2.0.2", - "async": "^3.2.3", - "is-stream": "^2.0.0", - "logform": "^2.4.0", - "one-time": "^1.0.0", - "readable-stream": "^3.4.0", - "safe-stable-stringify": "^2.3.1", - "stack-trace": "0.0.x", - "triple-beam": "^1.3.0", - "winston-transport": "^4.5.0" - }, - "dependencies": { - "readable-stream": { - "version": "3.6.0", - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } - } - }, - "winston-daily-rotate-file": { - "version": "4.7.1", - "requires": { - "file-stream-rotator": "^0.6.1", - "object-hash": "^2.0.1", - "triple-beam": "^1.3.0", - "winston-transport": "^4.4.0" - } - }, - "winston-transport": { - "version": "4.5.0", - "requires": { - "logform": "^2.3.2", - "readable-stream": "^3.6.0", - "triple-beam": "^1.3.0" - }, - "dependencies": { - "readable-stream": { - "version": "3.6.0", - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } - } - }, - "word-wrap": { - "version": "1.2.3", - "dev": true - }, - "wordwrap": { - "version": "1.0.0", - "dev": true - }, - "wrap-ansi": { - "version": "7.0.0", - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "dependencies": { - "emoji-regex": { - "version": "8.0.0" - }, - "is-fullwidth-code-point": { - "version": "3.0.0" - }, - "string-width": { - "version": "4.2.3", - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - } - } - }, - "wrappy": { - "version": "1.0.2", - "dev": true - }, - "write": { - "version": "0.2.1", - "dev": true, - "requires": { - "mkdirp": "^0.5.1" - } - }, - "write-file-atomic": { - "version": "3.0.3", - "dev": true, - "requires": { - "imurmurhash": "^0.1.4", - "is-typedarray": "^1.0.0", - "signal-exit": "^3.0.2", - "typedarray-to-buffer": "^3.1.5" - } - }, - "ws": { - "version": "7.5.9", - "requires": {} - }, - "xml2js": { - "version": "0.4.23", - "requires": { - "sax": ">=0.6.0", - "xmlbuilder": "~11.0.0" - } - }, - "xmlbuilder": { - "version": "11.0.1" - }, - "xor-distance": { - "version": "2.0.0" - }, - "xsalsa20": { - "version": "1.2.0" - }, - "xtend": { - "version": "4.0.2", - "dev": true - }, - "y18n": { - "version": "5.0.8" - }, - "yaml": { - "version": "2.1.3", - "dev": true - }, - "yargs": { - "version": "16.2.0", - "dev": true, - "requires": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - }, - "dependencies": { - "emoji-regex": { - "version": "8.0.0", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "dev": true - }, - "string-width": { - "version": "4.2.3", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - } - } - }, - "yargs-parser": { - "version": "20.2.9", - "dev": true - }, - "yn": { - "version": "3.1.1", - "dev": true - }, - "yocto-queue": { - "version": "0.1.0" - } - } -} diff --git a/packages/blockchain/karma.conf.js b/packages/blockchain/karma.conf.js index 9e3155bd4e..e46d2e1c0d 100644 --- a/packages/blockchain/karma.conf.js +++ b/packages/blockchain/karma.conf.js @@ -15,7 +15,7 @@ module.exports = function (config) { }, resolve: { alias: { - 'bigint-crypto-utils': '../../node_modules/bigint-crypto-utils/dist/bundles/umd.js', + 'bigint-crypto-utils': '../../node_modules/bigint-crypto-utils/dist/bundle.umd.js', '@chainsafe/persistent-merkle-tree/hasher': '../../node_modules/@chainsafe/persistent-merkle-tree/lib/hasher/noble.js', '@chainsafe/as-sha256/hashObject': diff --git a/packages/ethash/package.json b/packages/ethash/package.json index 3e08386147..f2d1bf4068 100644 --- a/packages/ethash/package.json +++ b/packages/ethash/package.json @@ -40,7 +40,7 @@ "@ethereumjs/block": "^4.2.1", "@ethereumjs/rlp": "^4.0.1", "@ethereumjs/util": "^8.0.5", - "bigint-crypto-utils": "^3.0.23", + "bigint-crypto-utils": "^3.2.2", "ethereum-cryptography": "^2.0.0" }, "devDependencies": { diff --git a/packages/evm/karma.conf.js b/packages/evm/karma.conf.js index 96b97bb756..cff4c36e72 100644 --- a/packages/evm/karma.conf.js +++ b/packages/evm/karma.conf.js @@ -28,7 +28,7 @@ module.exports = function (config) { }, resolve: { alias: { - 'bigint-crypto-utils': '../../node_modules/bigint-crypto-utils/dist/bundles/umd.js', + 'bigint-crypto-utils': '../../node_modules/bigint-crypto-utils/dist/bundle.umd.js', '@chainsafe/persistent-merkle-tree/hasher': '../../node_modules/@chainsafe/persistent-merkle-tree/lib/hasher/noble.js', '@chainsafe/as-sha256/hashObject': diff --git a/packages/statemanager/karma.conf.js b/packages/statemanager/karma.conf.js index fbbfbe51f8..bccba57c64 100644 --- a/packages/statemanager/karma.conf.js +++ b/packages/statemanager/karma.conf.js @@ -23,7 +23,7 @@ module.exports = function (config) { }, resolve: { alias: { - 'bigint-crypto-utils': '../../node_modules/bigint-crypto-utils/dist/bundles/umd.js', + 'bigint-crypto-utils': '../../node_modules/bigint-crypto-utils/dist/bundle.umd.js', '@chainsafe/persistent-merkle-tree/hasher': '../../node_modules/@chainsafe/persistent-merkle-tree/lib/hasher/noble.js', '@chainsafe/as-sha256/hashObject': diff --git a/packages/trie/karma.conf.js b/packages/trie/karma.conf.js index dce9a7f6b5..52867b6326 100644 --- a/packages/trie/karma.conf.js +++ b/packages/trie/karma.conf.js @@ -15,7 +15,7 @@ module.exports = function (config) { }, resolve: { alias: { - 'bigint-crypto-utils': '../../node_modules/bigint-crypto-utils/dist/bundles/umd.js', + 'bigint-crypto-utils': '../../node_modules/bigint-crypto-utils/dist/bundle.umd.js', '@chainsafe/persistent-merkle-tree/hasher': '../../node_modules/@chainsafe/persistent-merkle-tree/lib/hasher/noble.js', '@chainsafe/as-sha256/hashObject': diff --git a/packages/vm/karma.conf.js b/packages/vm/karma.conf.js index 0e3ecd7941..4195bf671b 100644 --- a/packages/vm/karma.conf.js +++ b/packages/vm/karma.conf.js @@ -28,7 +28,7 @@ module.exports = function (config) { }, resolve: { alias: { - 'bigint-crypto-utils': '../../node_modules/bigint-crypto-utils/dist/bundles/umd.js', + 'bigint-crypto-utils': '../../node_modules/bigint-crypto-utils/dist/bundle.umd.js', '@chainsafe/persistent-merkle-tree/hasher': '../../node_modules/@chainsafe/persistent-merkle-tree/lib/hasher/noble.js', '@chainsafe/as-sha256/hashObject': From f291148d9dbc75600f9d66e0d0adad7e72f32d1b Mon Sep 17 00:00:00 2001 From: Frederik Bolding Date: Fri, 21 Apr 2023 20:18:19 +0200 Subject: [PATCH 43/53] Bump chainsafe/ssz to 0.11.1 (#2656) --- packages/block/karma.conf.js | 9 --------- packages/blockchain/karma.conf.js | 4 ---- packages/client/karma.conf.js | 4 ---- packages/common/karma.conf.js | 8 -------- packages/evm/karma.conf.js | 4 ---- packages/statemanager/karma.conf.js | 4 ---- packages/trie/karma.conf.js | 4 ---- packages/tx/karma.conf.js | 9 --------- packages/tx/package.json | 2 +- packages/util/karma.conf.js | 8 -------- packages/util/package.json | 2 +- packages/vm/karma.conf.js | 4 ---- 12 files changed, 2 insertions(+), 60 deletions(-) diff --git a/packages/block/karma.conf.js b/packages/block/karma.conf.js index 81b7570427..3cdcf9821e 100644 --- a/packages/block/karma.conf.js +++ b/packages/block/karma.conf.js @@ -13,15 +13,6 @@ module.exports = function (config) { acornOptions: { ecmaVersion: 12, }, - resolve: { - alias: { - '@chainsafe/persistent-merkle-tree/hasher': - '../../node_modules/@chainsafe/persistent-merkle-tree/lib/hasher/noble.js', - '@chainsafe/as-sha256/hashObject': - '../../node_modules/@chainsafe/as-sha256/lib/hashObject.js', - }, - }, - ignore: ['c-kzg'], }, }, concurrency: 1, diff --git a/packages/blockchain/karma.conf.js b/packages/blockchain/karma.conf.js index e46d2e1c0d..8597acfd8f 100644 --- a/packages/blockchain/karma.conf.js +++ b/packages/blockchain/karma.conf.js @@ -16,10 +16,6 @@ module.exports = function (config) { resolve: { alias: { 'bigint-crypto-utils': '../../node_modules/bigint-crypto-utils/dist/bundle.umd.js', - '@chainsafe/persistent-merkle-tree/hasher': - '../../node_modules/@chainsafe/persistent-merkle-tree/lib/hasher/noble.js', - '@chainsafe/as-sha256/hashObject': - '../../node_modules/@chainsafe/as-sha256/lib/hashObject.js', }, }, }, diff --git a/packages/client/karma.conf.js b/packages/client/karma.conf.js index f9bcfe6839..c0784cd817 100644 --- a/packages/client/karma.conf.js +++ b/packages/client/karma.conf.js @@ -26,10 +26,6 @@ module.exports = function (config) { '../../node_modules/multiformats/cjs/src/hashes/identity.js', 'multiformats/hashes/sha2': '../../node_modules/multiformats/cjs/src/hashes/sha2-browser.js', - '@chainsafe/persistent-merkle-tree/hasher': - '../../node_modules/@chainsafe/persistent-merkle-tree/lib/hasher/noble.js', - '@chainsafe/as-sha256/hashObject': - '../../node_modules/@chainsafe/as-sha256/lib/hashObject.js', }, }, diff --git a/packages/common/karma.conf.js b/packages/common/karma.conf.js index cb8bed8f8a..3cdcf9821e 100644 --- a/packages/common/karma.conf.js +++ b/packages/common/karma.conf.js @@ -13,14 +13,6 @@ module.exports = function (config) { acornOptions: { ecmaVersion: 12, }, - resolve: { - alias: { - '@chainsafe/persistent-merkle-tree/hasher': - '../../node_modules/@chainsafe/persistent-merkle-tree/lib/hasher/noble.js', - '@chainsafe/as-sha256/hashObject': - '../../node_modules/@chainsafe/as-sha256/lib/hashObject.js', - }, - }, }, }, concurrency: 1, diff --git a/packages/evm/karma.conf.js b/packages/evm/karma.conf.js index cff4c36e72..1f9879793c 100644 --- a/packages/evm/karma.conf.js +++ b/packages/evm/karma.conf.js @@ -29,10 +29,6 @@ module.exports = function (config) { resolve: { alias: { 'bigint-crypto-utils': '../../node_modules/bigint-crypto-utils/dist/bundle.umd.js', - '@chainsafe/persistent-merkle-tree/hasher': - '../../node_modules/@chainsafe/persistent-merkle-tree/lib/hasher/noble.js', - '@chainsafe/as-sha256/hashObject': - '../../node_modules/@chainsafe/as-sha256/lib/hashObject.js', }, }, }, diff --git a/packages/statemanager/karma.conf.js b/packages/statemanager/karma.conf.js index bccba57c64..4c037ddab5 100644 --- a/packages/statemanager/karma.conf.js +++ b/packages/statemanager/karma.conf.js @@ -24,10 +24,6 @@ module.exports = function (config) { resolve: { alias: { 'bigint-crypto-utils': '../../node_modules/bigint-crypto-utils/dist/bundle.umd.js', - '@chainsafe/persistent-merkle-tree/hasher': - '../../node_modules/@chainsafe/persistent-merkle-tree/lib/hasher/noble.js', - '@chainsafe/as-sha256/hashObject': - '../../node_modules/@chainsafe/as-sha256/lib/hashObject.js', }, }, }, diff --git a/packages/trie/karma.conf.js b/packages/trie/karma.conf.js index 52867b6326..86190b3d4c 100644 --- a/packages/trie/karma.conf.js +++ b/packages/trie/karma.conf.js @@ -16,10 +16,6 @@ module.exports = function (config) { resolve: { alias: { 'bigint-crypto-utils': '../../node_modules/bigint-crypto-utils/dist/bundle.umd.js', - '@chainsafe/persistent-merkle-tree/hasher': - '../../node_modules/@chainsafe/persistent-merkle-tree/lib/hasher/noble.js', - '@chainsafe/as-sha256/hashObject': - '../../node_modules/@chainsafe/as-sha256/lib/hashObject.js', }, }, }, diff --git a/packages/tx/karma.conf.js b/packages/tx/karma.conf.js index 01e70794c7..5f921f9078 100644 --- a/packages/tx/karma.conf.js +++ b/packages/tx/karma.conf.js @@ -15,15 +15,6 @@ module.exports = function (config) { acornOptions: { ecmaVersion: 12, }, - ignore: ['c-kzg', 'safer-buffer'], - resolve: { - alias: { - '@chainsafe/persistent-merkle-tree/hasher': - '../../node_modules/@chainsafe/persistent-merkle-tree/lib/hasher/noble.js', - '@chainsafe/as-sha256/hashObject': - '../../node_modules/@chainsafe/as-sha256/lib/hashObject.js', - }, - }, }, }, browsers: ['FirefoxHeadless', 'ChromeHeadless'], diff --git a/packages/tx/package.json b/packages/tx/package.json index d59b06f014..86d25ef3aa 100644 --- a/packages/tx/package.json +++ b/packages/tx/package.json @@ -51,7 +51,7 @@ "tsc": "../../config/cli/ts-compile.sh" }, "dependencies": { - "@chainsafe/ssz": "^0.11.0", + "@chainsafe/ssz": "^0.11.1", "@ethereumjs/common": "^3.1.1", "@ethereumjs/rlp": "^4.0.1", "@ethereumjs/util": "^8.0.5", diff --git a/packages/util/karma.conf.js b/packages/util/karma.conf.js index a92b1a43ae..1bdb8ce5b9 100644 --- a/packages/util/karma.conf.js +++ b/packages/util/karma.conf.js @@ -11,14 +11,6 @@ module.exports = function (config) { acornOptions: { ecmaVersion: 12, }, - resolve: { - alias: { - '@chainsafe/persistent-merkle-tree/hasher': - '../../node_modules/@chainsafe/persistent-merkle-tree/lib/hasher/noble.js', - '@chainsafe/as-sha256/hashObject': - '../../node_modules/@chainsafe/as-sha256/lib/hashObject.js', - }, - }, }, tsconfig: './tsconfig.json', }, diff --git a/packages/util/package.json b/packages/util/package.json index eb355782bf..2bfd322f07 100644 --- a/packages/util/package.json +++ b/packages/util/package.json @@ -83,7 +83,7 @@ "tsc": "../../config/cli/ts-compile.sh" }, "dependencies": { - "@chainsafe/ssz": "^0.11.0", + "@chainsafe/ssz": "^0.11.1", "@ethereumjs/rlp": "^4.0.1", "ethereum-cryptography": "^2.0.0" }, diff --git a/packages/vm/karma.conf.js b/packages/vm/karma.conf.js index 4195bf671b..4b248f143e 100644 --- a/packages/vm/karma.conf.js +++ b/packages/vm/karma.conf.js @@ -29,10 +29,6 @@ module.exports = function (config) { resolve: { alias: { 'bigint-crypto-utils': '../../node_modules/bigint-crypto-utils/dist/bundle.umd.js', - '@chainsafe/persistent-merkle-tree/hasher': - '../../node_modules/@chainsafe/persistent-merkle-tree/lib/hasher/noble.js', - '@chainsafe/as-sha256/hashObject': - '../../node_modules/@chainsafe/as-sha256/lib/hashObject.js', }, }, ignore: ['c-kzg', 'safer-buffer'], From 10658a716ef1d16fe9d0e9fb017a0aed730ee605 Mon Sep 17 00:00:00 2001 From: Holger Drewes Date: Mon, 24 Apr 2023 09:35:03 +0200 Subject: [PATCH 44/53] New Maintenance Release Round (#2648) * Draft various release notes * CHANGELOG updates * Version bump, updated upstream dependency versions, @ethereumjs/util v8.0.6 * Version bump, updated upstream dependency versions, @ethereumjs/common v3.1.2 * Version bump, updated upstream dependency versions, @ethereumjs/tx v4.1.2 * Version bump, updated upstream dependency versions, @ethereumjs/trie v5.0.5 * Add additional @chainsafe/ssz notes to CHANGELOG files of other libraries * Version bump, updated upstream dependency versions, updated (all) client @ethereumjs dependencies, @ethereumjs/devp2p v5.1.2 * Version bump, updated upstream dependency versions, @ethereumjs/statemanager v1.0.5 * Version bump, updated upstream dependency versions, @ethereumjs/block v4.2.2 * Version bump, updated upstream dependency versions, @ethereumjs/ethash v2.0.5 * Version bump, updated upstream dependency versions, @ethereumjs/blockchain v6.2.2 * Version bump, updated upstream dependency versions, @ethereumjs/evm v1.3.2 * Version bump, updated upstream dependency versions, @ethereumjs/vm v6.4.2 * Version bump, @ethereumjs/client v0.7.1 * Rebuild package-lock.json * Rebuild relevant documentation * Updated @chainsafe/ssz related CHANGELOG entries --- packages/block/CHANGELOG.md | 12 + packages/block/docs/README.md | 12 +- packages/block/docs/classes/Block.md | 112 +- packages/block/docs/classes/BlockHeader.md | 55 +- packages/block/docs/interfaces/BlockData.md | 10 +- packages/block/docs/interfaces/HeaderData.md | 11 + packages/block/docs/interfaces/JsonBlock.md | 8 +- packages/block/docs/interfaces/JsonHeader.md | 45 +- .../block/docs/interfaces/JsonRpcBlock.md | 66 +- packages/block/package.json | 10 +- packages/blockchain/CHANGELOG.md | 5 + .../blockchain/docs/classes/Blockchain.md | 10 +- packages/blockchain/package.json | 14 +- packages/client/CHANGELOG.md | 15 + packages/client/package.json | 24 +- packages/common/CHANGELOG.md | 6 + packages/common/docs/README.md | 2 +- packages/common/package.json | 4 +- packages/devp2p/CHANGELOG.md | 5 + packages/devp2p/package.json | 10 +- packages/ethash/CHANGELOG.md | 5 + packages/ethash/package.json | 8 +- packages/evm/CHANGELOG.md | 24 + packages/evm/docs/interfaces/EVMResult.md | 4 +- packages/evm/docs/interfaces/ExecResult.md | 16 +- packages/evm/package.json | 10 +- packages/statemanager/CHANGELOG.md | 5 + packages/statemanager/docs/README.md | 21 + packages/statemanager/package.json | 10 +- packages/trie/CHANGELOG.md | 5 + packages/trie/package.json | 4 +- packages/tx/CHANGELOG.md | 18 + packages/tx/docs/README.md | 182 +++- .../classes/AccessListEIP2930Transaction.md | 60 +- .../tx/docs/classes/BlobEIP4844Transaction.md | 997 ++++++++++++++++++ .../classes/FeeMarketEIP1559Transaction.md | 60 +- packages/tx/docs/classes/Transaction.md | 72 +- .../tx/docs/classes/TransactionFactory.md | 37 +- packages/tx/docs/enums/Capability.md | 8 +- .../interfaces/AccessListEIP2930TxData.md | 28 +- .../tx/docs/interfaces/BlobEIP4844TxData.md | 320 ++++++ .../docs/interfaces/FeeMarketEIP1559TxData.md | 34 +- packages/tx/docs/interfaces/JsonRpcTx.md | 60 +- packages/tx/docs/interfaces/JsonTx.md | 50 +- packages/tx/docs/interfaces/TxOptions.md | 18 +- packages/tx/package.json | 6 +- packages/util/CHANGELOG.md | 5 + packages/util/docs/README.md | 216 +++- packages/util/package.json | 2 +- packages/vm/CHANGELOG.md | 15 + packages/vm/docs/README.md | 10 +- packages/vm/package.json | 18 +- 52 files changed, 2361 insertions(+), 403 deletions(-) create mode 100644 packages/tx/docs/classes/BlobEIP4844Transaction.md create mode 100644 packages/tx/docs/interfaces/BlobEIP4844TxData.md diff --git a/packages/block/CHANGELOG.md b/packages/block/CHANGELOG.md index b37d7b5f4e..6b9574135f 100644 --- a/packages/block/CHANGELOG.md +++ b/packages/block/CHANGELOG.md @@ -6,6 +6,18 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) (modification: no type change headlines) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). +## 4.2.2 - 2023-04-20 + +### Bugfixes + +- Throw if EIP-4895 is active and no withdrawals are available, PR [#2601](https://github.com/ethereumjs/ethereumjs-monorepo/pull/2601) + +### Maintenance + +- Removed `Ethers` dependency, alternative `fromEthersProvider()` static constructor implementation, PR [#2633](https://github.com/ethereumjs/ethereumjs-monorepo/pull/2633) +- Bump `@ethereumjs/util` `@chainsafe/ssz` dependency to 0.11.1 (no WASM, native SHA-256 implementation, ES2019 compatible, explicit imports), PRs [#2622](https://github.com/ethereumjs/ethereumjs-monorepo/pull/2622), [#2564](https://github.com/ethereumjs/ethereumjs-monorepo/pull/2564) and [#2656](https://github.com/ethereumjs/ethereumjs-monorepo/pull/2656) +- Update ethereum-cryptography from 1.2 to 2.0 (switch from noble-secp256k1 to noble-curves), PR [#2641](https://github.com/ethereumjs/ethereumjs-monorepo/pull/2641) + ## 4.2.1 - 2023-02-27 - Pinned `@ethereumjs/util` `@chainsafe/ssz` dependency to `v0.9.4` due to ES2021 features used in `v0.10.+` causing compatibility issues, PR [#2555](https://github.com/ethereumjs/ethereumjs-monorepo/pull/2555) diff --git a/packages/block/docs/README.md b/packages/block/docs/README.md index c91a6e3854..9e7d90f474 100644 --- a/packages/block/docs/README.md +++ b/packages/block/docs/README.md @@ -35,7 +35,7 @@ #### Defined in -[types.ts:128](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L128) +[types.ts:129](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L129) ___ @@ -45,7 +45,7 @@ ___ #### Defined in -[types.ts:124](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L124) +[types.ts:125](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L125) ___ @@ -55,7 +55,7 @@ ___ #### Defined in -[types.ts:127](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L127) +[types.ts:128](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L128) ___ @@ -67,7 +67,7 @@ TransactionsBuffer can be an array of serialized txs for Typed Transactions or a #### Defined in -[types.ts:132](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L132) +[types.ts:133](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L133) ___ @@ -77,7 +77,7 @@ ___ #### Defined in -[types.ts:133](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L133) +[types.ts:134](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L134) ___ @@ -87,4 +87,4 @@ ___ #### Defined in -[types.ts:122](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L122) +[types.ts:123](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L123) diff --git a/packages/block/docs/classes/Block.md b/packages/block/docs/classes/Block.md index ed3ced6443..c6fcf9b9d2 100644 --- a/packages/block/docs/classes/Block.md +++ b/packages/block/docs/classes/Block.md @@ -29,6 +29,7 @@ An object that represents the block. - [raw](Block.md#raw) - [serialize](Block.md#serialize) - [toJSON](Block.md#tojson) +- [validateBlobTransactions](Block.md#validateblobtransactions) - [validateData](Block.md#validatedata) - [validateGasLimit](Block.md#validategaslimit) - [validateTransactions](Block.md#validatetransactions) @@ -43,6 +44,7 @@ An object that represents the block. - [fromValuesArray](Block.md#fromvaluesarray) - [genTransactionsTrieRoot](Block.md#gentransactionstrieroot) - [genWithdrawalsTrieRoot](Block.md#genwithdrawalstrieroot) +- [generateWithdrawalsSSZRoot](Block.md#generatewithdrawalssszroot) ## Constructors @@ -65,7 +67,7 @@ Use the static factory methods to assist in creating a Block object from varying #### Defined in -[block.ts:255](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/block.ts#L255) +[block.ts:289](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/block.ts#L289) ## Properties @@ -75,7 +77,7 @@ Use the static factory methods to assist in creating a Block object from varying #### Defined in -[block.ts:40](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/block.ts#L40) +[block.ts:43](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/block.ts#L43) ___ @@ -85,7 +87,7 @@ ___ #### Defined in -[block.ts:35](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/block.ts#L35) +[block.ts:38](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/block.ts#L38) ___ @@ -95,7 +97,7 @@ ___ #### Defined in -[block.ts:36](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/block.ts#L36) +[block.ts:39](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/block.ts#L39) ___ @@ -105,7 +107,7 @@ ___ #### Defined in -[block.ts:39](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/block.ts#L39) +[block.ts:42](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/block.ts#L42) ___ @@ -115,7 +117,7 @@ ___ #### Defined in -[block.ts:37](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/block.ts#L37) +[block.ts:40](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/block.ts#L40) ___ @@ -125,7 +127,7 @@ ___ #### Defined in -[block.ts:38](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/block.ts#L38) +[block.ts:41](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/block.ts#L41) ## Methods @@ -141,7 +143,7 @@ Return a compact error string representation of the object #### Defined in -[block.ts:518](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/block.ts#L518) +[block.ts:586](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/block.ts#L586) ___ @@ -163,7 +165,7 @@ Returns the canonical difficulty for this block. #### Defined in -[block.ts:484](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/block.ts#L484) +[block.ts:552](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/block.ts#L552) ___ @@ -179,7 +181,7 @@ Generates transaction trie for validation. #### Defined in -[block.ts:337](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/block.ts#L337) +[block.ts:370](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/block.ts#L370) ___ @@ -195,7 +197,7 @@ Returns the hash of the block. #### Defined in -[block.ts:316](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/block.ts#L316) +[block.ts:349](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/block.ts#L349) ___ @@ -211,7 +213,7 @@ Determines if this block is the genesis block. #### Defined in -[block.ts:323](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/block.ts#L323) +[block.ts:356](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/block.ts#L356) ___ @@ -227,7 +229,7 @@ Returns a Buffer Array of the raw Buffers of this block, in order. #### Defined in -[block.ts:298](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/block.ts#L298) +[block.ts:331](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/block.ts#L331) ___ @@ -243,7 +245,7 @@ Returns the rlp encoding of the block. #### Defined in -[block.ts:330](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/block.ts#L330) +[block.ts:363](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/block.ts#L363) ___ @@ -259,7 +261,31 @@ Returns the block in JSON format. #### Defined in -[block.ts:501](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/block.ts#L501) +[block.ts:569](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/block.ts#L569) + +___ + +### validateBlobTransactions + +▸ **validateBlobTransactions**(`parentHeader`): `void` + +Validates that data gas fee for each transaction is greater than or equal to the +dataGasPrice for the block and that total data gas in block is less than maximum +data gas per block + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `parentHeader` | [`BlockHeader`](BlockHeader.md) | header of parent block | + +#### Returns + +`void` + +#### Defined in + +[block.ts:484](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/block.ts#L484) ___ @@ -286,7 +312,7 @@ It checks: #### Defined in -[block.ts:403](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/block.ts#L403) +[block.ts:450](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/block.ts#L450) ___ @@ -309,7 +335,7 @@ Throws if invalid #### Defined in -[block.ts:494](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/block.ts#L494) +[block.ts:562](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/block.ts#L562) ___ @@ -325,7 +351,7 @@ Validates transaction signatures and minimum gas requirements. #### Defined in -[block.ts:365](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/block.ts#L365) +[block.ts:398](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/block.ts#L398) ▸ **validateTransactions**(`stringError`): `boolean` @@ -341,7 +367,7 @@ Validates transaction signatures and minimum gas requirements. #### Defined in -[block.ts:366](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/block.ts#L366) +[block.ts:399](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/block.ts#L399) ▸ **validateTransactions**(`stringError`): `string`[] @@ -357,7 +383,7 @@ Validates transaction signatures and minimum gas requirements. #### Defined in -[block.ts:367](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/block.ts#L367) +[block.ts:400](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/block.ts#L400) ___ @@ -374,7 +400,7 @@ and do a check on the root hash. #### Defined in -[block.ts:346](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/block.ts#L346) +[block.ts:379](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/block.ts#L379) ___ @@ -396,7 +422,7 @@ Header does not count an uncle twice. #### Defined in -[block.ts:460](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/block.ts#L460) +[block.ts:528](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/block.ts#L528) ___ @@ -412,7 +438,7 @@ Validates the uncle's hash. #### Defined in -[block.ts:434](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/block.ts#L434) +[block.ts:502](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/block.ts#L502) ___ @@ -428,7 +454,7 @@ Validates the withdrawal root #### Defined in -[block.ts:443](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/block.ts#L443) +[block.ts:511](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/block.ts#L511) ___ @@ -451,7 +477,7 @@ Static constructor to create a block from a block data dictionary #### Defined in -[block.ts:74](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/block.ts#L74) +[block.ts:85](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/block.ts#L85) ___ @@ -465,7 +491,7 @@ Method to retrieve a block from the provider and format as a [Block](Block.md) | Name | Type | Description | | :------ | :------ | :------ | -| `provider` | `string` \| `JsonRpcProvider` | an Ethers JsonRPCProvider | +| `provider` | `any` | an Ethers JsonRPCProvider | | `blockTag` | `string` \| `bigint` | block hash or block number to be run | | `opts` | [`BlockOptions`](../interfaces/BlockOptions.md) | [BlockOptions](../interfaces/BlockOptions.md) | @@ -477,7 +503,7 @@ the block specified by `blockTag` #### Defined in -[block.ts:212](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/block.ts#L212) +[block.ts:233](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/block.ts#L233) ___ @@ -500,7 +526,7 @@ Static constructor to create a block from a RLP-serialized block #### Defined in -[block.ts:126](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/block.ts#L126) +[block.ts:137](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/block.ts#L137) ___ @@ -524,7 +550,7 @@ Creates a new block object from Ethereum JSON RPC. #### Defined in -[block.ts:201](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/block.ts#L201) +[block.ts:222](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/block.ts#L222) ___ @@ -547,7 +573,7 @@ Static constructor to create a block from an array of Buffer values #### Defined in -[block.ts:142](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/block.ts#L142) +[block.ts:153](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/block.ts#L153) ___ @@ -570,7 +596,7 @@ Returns the txs trie root for array of TypedTransaction #### Defined in -[block.ts:60](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/block.ts#L60) +[block.ts:71](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/block.ts#L71) ___ @@ -593,4 +619,26 @@ Returns the withdrawals trie root for array of Withdrawal. #### Defined in -[block.ts:47](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/block.ts#L47) +[block.ts:50](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/block.ts#L50) + +___ + +### generateWithdrawalsSSZRoot + +▸ `Static` **generateWithdrawalsSSZRoot**(`withdrawals`): `Promise`<`void`\> + +Returns the ssz root for array of withdrawal transactions. + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `withdrawals` | `Withdrawal`[] | + +#### Returns + +`Promise`<`void`\> + +#### Defined in + +[block.ts:62](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/block.ts#L62) diff --git a/packages/block/docs/classes/BlockHeader.md b/packages/block/docs/classes/BlockHeader.md index 1e36a62458..b5a101eaed 100644 --- a/packages/block/docs/classes/BlockHeader.md +++ b/packages/block/docs/classes/BlockHeader.md @@ -16,6 +16,7 @@ An object that represents the block header. - [baseFeePerGas](BlockHeader.md#basefeepergas) - [coinbase](BlockHeader.md#coinbase) - [difficulty](BlockHeader.md#difficulty) +- [excessDataGas](BlockHeader.md#excessdatagas) - [extraData](BlockHeader.md#extradata) - [gasLimit](BlockHeader.md#gaslimit) - [gasUsed](BlockHeader.md#gasused) @@ -81,7 +82,7 @@ varying data types. For a default empty header, use [fromHeaderData](BlockHeader #### Defined in -[header.ts:125](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/header.ts#L125) +[header.ts:126](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/header.ts#L126) ## Properties @@ -91,7 +92,7 @@ varying data types. For a default empty header, use [fromHeaderData](BlockHeader #### Defined in -[header.ts:56](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/header.ts#L56) +[header.ts:57](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/header.ts#L57) ___ @@ -125,6 +126,16 @@ ___ ___ +### excessDataGas + +• `Optional` `Readonly` **excessDataGas**: `bigint` + +#### Defined in + +[header.ts:55](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/header.ts#L55) + +___ + ### extraData • `Readonly` **extraData**: `Buffer` @@ -277,7 +288,7 @@ EIP-4399: After merge to PoS, `mixHash` supplanted as `prevRandao` #### Defined in -[header.ts:65](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/header.ts#L65) +[header.ts:66](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/header.ts#L66) ## Methods @@ -329,7 +340,7 @@ Calculates the base fee for a potential next block #### Defined in -[header.ts:476](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/header.ts#L476) +[header.ts:481](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/header.ts#L481) ___ @@ -350,7 +361,7 @@ in conjunction with [cliqueIsEpochTransition](BlockHeader.md#cliqueisepochtransi #### Defined in -[header.ts:723](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/header.ts#L723) +[header.ts:731](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/header.ts#L731) ___ @@ -367,7 +378,7 @@ Returns extra seal data #### Defined in -[header.ts:690](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/header.ts#L690) +[header.ts:698](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/header.ts#L698) ___ @@ -384,7 +395,7 @@ Returns extra vanity data #### Defined in -[header.ts:681](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/header.ts#L681) +[header.ts:689](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/header.ts#L689) ___ @@ -401,7 +412,7 @@ header (only clique PoA, throws otherwise) #### Defined in -[header.ts:669](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/header.ts#L669) +[header.ts:677](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/header.ts#L677) ___ @@ -417,7 +428,7 @@ PoA clique signature hash without the seal. #### Defined in -[header.ts:658](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/header.ts#L658) +[header.ts:666](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/header.ts#L666) ___ @@ -433,7 +444,7 @@ Returns the signer address #### Defined in -[header.ts:760](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/header.ts#L760) +[header.ts:768](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/header.ts#L768) ___ @@ -458,7 +469,7 @@ Verifies the signature of the block (last 65 bytes of extraData field) #### Defined in -[header.ts:748](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/header.ts#L748) +[header.ts:756](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/header.ts#L756) ___ @@ -474,7 +485,7 @@ Return a compact error string representation of the object #### Defined in -[header.ts:836](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/header.ts#L836) +[header.ts:847](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/header.ts#L847) ___ @@ -496,7 +507,7 @@ Returns the canonical difficulty for this block. #### Defined in -[header.ts:585](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/header.ts#L585) +[header.ts:593](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/header.ts#L593) ___ @@ -512,7 +523,7 @@ Returns the hash of the block header. #### Defined in -[header.ts:553](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/header.ts#L553) +[header.ts:561](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/header.ts#L561) ___ @@ -528,7 +539,7 @@ Checks if the block header is a genesis header. #### Defined in -[header.ts:567](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/header.ts#L567) +[header.ts:575](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/header.ts#L575) ___ @@ -544,7 +555,7 @@ Returns a Buffer Array of the raw Buffers in this header, in order. #### Defined in -[header.ts:520](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/header.ts#L520) +[header.ts:525](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/header.ts#L525) ___ @@ -560,7 +571,7 @@ Returns the rlp encoding of the block header. #### Defined in -[header.ts:777](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/header.ts#L777) +[header.ts:785](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/header.ts#L785) ___ @@ -576,7 +587,7 @@ Returns the block header in JSON format. #### Defined in -[header.ts:784](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/header.ts#L784) +[header.ts:792](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/header.ts#L792) ___ @@ -599,7 +610,7 @@ Throws if out of bounds. #### Defined in -[header.ts:434](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/header.ts#L434) +[header.ts:439](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/header.ts#L439) ___ @@ -622,7 +633,7 @@ Static constructor to create a block header from a header data dictionary #### Defined in -[header.ts:81](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/header.ts#L81) +[header.ts:82](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/header.ts#L82) ___ @@ -645,7 +656,7 @@ Static constructor to create a block header from a RLP-serialized header #### Defined in -[header.ts:91](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/header.ts#L91) +[header.ts:92](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/header.ts#L92) ___ @@ -668,4 +679,4 @@ Static constructor to create a block header from an array of Buffer values #### Defined in -[header.ts:105](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/header.ts#L105) +[header.ts:106](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/header.ts#L106) diff --git a/packages/block/docs/interfaces/BlockData.md b/packages/block/docs/interfaces/BlockData.md index 8367fd900f..8dcaf44d7b 100644 --- a/packages/block/docs/interfaces/BlockData.md +++ b/packages/block/docs/interfaces/BlockData.md @@ -23,17 +23,17 @@ Header data for the block #### Defined in -[types.ts:116](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L116) +[types.ts:117](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L117) ___ ### transactions -• `Optional` **transactions**: (`AccessListEIP2930TxData` \| `TxData` \| `FeeMarketEIP1559TxData`)[] +• `Optional` **transactions**: (`AccessListEIP2930TxData` \| `FeeMarketEIP1559TxData` \| `TxData`)[] #### Defined in -[types.ts:117](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L117) +[types.ts:118](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L118) ___ @@ -43,7 +43,7 @@ ___ #### Defined in -[types.ts:118](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L118) +[types.ts:119](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L119) ___ @@ -53,4 +53,4 @@ ___ #### Defined in -[types.ts:119](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L119) +[types.ts:120](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L120) diff --git a/packages/block/docs/interfaces/HeaderData.md b/packages/block/docs/interfaces/HeaderData.md index 73b0baa070..e50f98e3ce 100644 --- a/packages/block/docs/interfaces/HeaderData.md +++ b/packages/block/docs/interfaces/HeaderData.md @@ -11,6 +11,7 @@ A block header's data. - [baseFeePerGas](HeaderData.md#basefeepergas) - [coinbase](HeaderData.md#coinbase) - [difficulty](HeaderData.md#difficulty) +- [excessDataGas](HeaderData.md#excessdatagas) - [extraData](HeaderData.md#extradata) - [gasLimit](HeaderData.md#gaslimit) - [gasUsed](HeaderData.md#gasused) @@ -58,6 +59,16 @@ ___ ___ +### excessDataGas + +• `Optional` **excessDataGas**: `BigIntLike` + +#### Defined in + +[types.ts:107](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L107) + +___ + ### extraData • `Optional` **extraData**: `BufferLike` diff --git a/packages/block/docs/interfaces/JsonBlock.md b/packages/block/docs/interfaces/JsonBlock.md index 836b8b3052..e94b9862fd 100644 --- a/packages/block/docs/interfaces/JsonBlock.md +++ b/packages/block/docs/interfaces/JsonBlock.md @@ -23,7 +23,7 @@ Header data for the block #### Defined in -[types.ts:142](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L142) +[types.ts:143](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L143) ___ @@ -33,7 +33,7 @@ ___ #### Defined in -[types.ts:143](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L143) +[types.ts:144](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L144) ___ @@ -43,7 +43,7 @@ ___ #### Defined in -[types.ts:144](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L144) +[types.ts:145](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L145) ___ @@ -53,4 +53,4 @@ ___ #### Defined in -[types.ts:145](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L145) +[types.ts:146](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L146) diff --git a/packages/block/docs/interfaces/JsonHeader.md b/packages/block/docs/interfaces/JsonHeader.md index 6306f3edd0..58ea6eaa6e 100644 --- a/packages/block/docs/interfaces/JsonHeader.md +++ b/packages/block/docs/interfaces/JsonHeader.md @@ -11,6 +11,7 @@ An object with the block header's data represented as strings. - [baseFeePerGas](JsonHeader.md#basefeepergas) - [coinbase](JsonHeader.md#coinbase) - [difficulty](JsonHeader.md#difficulty) +- [excessDataGas](JsonHeader.md#excessdatagas) - [extraData](JsonHeader.md#extradata) - [gasLimit](JsonHeader.md#gaslimit) - [gasUsed](JsonHeader.md#gasused) @@ -34,7 +35,7 @@ An object with the block header's data represented as strings. #### Defined in -[types.ts:167](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L167) +[types.ts:168](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L168) ___ @@ -44,7 +45,7 @@ ___ #### Defined in -[types.ts:154](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L154) +[types.ts:155](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L155) ___ @@ -54,7 +55,17 @@ ___ #### Defined in -[types.ts:159](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L159) +[types.ts:160](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L160) + +___ + +### excessDataGas + +• `Optional` **excessDataGas**: `string` + +#### Defined in + +[types.ts:170](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L170) ___ @@ -64,7 +75,7 @@ ___ #### Defined in -[types.ts:164](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L164) +[types.ts:165](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L165) ___ @@ -74,7 +85,7 @@ ___ #### Defined in -[types.ts:161](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L161) +[types.ts:162](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L162) ___ @@ -84,7 +95,7 @@ ___ #### Defined in -[types.ts:162](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L162) +[types.ts:163](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L163) ___ @@ -94,7 +105,7 @@ ___ #### Defined in -[types.ts:158](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L158) +[types.ts:159](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L159) ___ @@ -104,7 +115,7 @@ ___ #### Defined in -[types.ts:165](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L165) +[types.ts:166](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L166) ___ @@ -114,7 +125,7 @@ ___ #### Defined in -[types.ts:166](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L166) +[types.ts:167](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L167) ___ @@ -124,7 +135,7 @@ ___ #### Defined in -[types.ts:160](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L160) +[types.ts:161](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L161) ___ @@ -134,7 +145,7 @@ ___ #### Defined in -[types.ts:152](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L152) +[types.ts:153](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L153) ___ @@ -144,7 +155,7 @@ ___ #### Defined in -[types.ts:157](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L157) +[types.ts:158](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L158) ___ @@ -154,7 +165,7 @@ ___ #### Defined in -[types.ts:155](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L155) +[types.ts:156](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L156) ___ @@ -164,7 +175,7 @@ ___ #### Defined in -[types.ts:163](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L163) +[types.ts:164](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L164) ___ @@ -174,7 +185,7 @@ ___ #### Defined in -[types.ts:156](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L156) +[types.ts:157](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L157) ___ @@ -184,7 +195,7 @@ ___ #### Defined in -[types.ts:153](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L153) +[types.ts:154](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L154) ___ @@ -194,4 +205,4 @@ ___ #### Defined in -[types.ts:168](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L168) +[types.ts:169](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L169) diff --git a/packages/block/docs/interfaces/JsonRpcBlock.md b/packages/block/docs/interfaces/JsonRpcBlock.md index 65c4f5135c..f18bce10bb 100644 --- a/packages/block/docs/interfaces/JsonRpcBlock.md +++ b/packages/block/docs/interfaces/JsonRpcBlock.md @@ -8,6 +8,7 @@ - [baseFeePerGas](JsonRpcBlock.md#basefeepergas) - [difficulty](JsonRpcBlock.md#difficulty) +- [excessDataGas](JsonRpcBlock.md#excessdatagas) - [extraData](JsonRpcBlock.md#extradata) - [gasLimit](JsonRpcBlock.md#gaslimit) - [gasUsed](JsonRpcBlock.md#gasused) @@ -28,6 +29,7 @@ - [transactionsRoot](JsonRpcBlock.md#transactionsroot) - [uncles](JsonRpcBlock.md#uncles) - [withdrawals](JsonRpcBlock.md#withdrawals) +- [withdrawalsRoot](JsonRpcBlock.md#withdrawalsroot) ## Properties @@ -37,7 +39,7 @@ #### Defined in -[types.ts:195](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L195) +[types.ts:197](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L197) ___ @@ -47,7 +49,17 @@ ___ #### Defined in -[types.ts:186](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L186) +[types.ts:188](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L188) + +___ + +### excessDataGas + +• `Optional` **excessDataGas**: `string` + +#### Defined in + +[types.ts:200](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L200) ___ @@ -57,7 +69,7 @@ ___ #### Defined in -[types.ts:188](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L188) +[types.ts:190](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L190) ___ @@ -67,7 +79,7 @@ ___ #### Defined in -[types.ts:190](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L190) +[types.ts:192](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L192) ___ @@ -77,7 +89,7 @@ ___ #### Defined in -[types.ts:191](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L191) +[types.ts:193](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L193) ___ @@ -87,7 +99,7 @@ ___ #### Defined in -[types.ts:176](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L176) +[types.ts:178](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L178) ___ @@ -97,7 +109,7 @@ ___ #### Defined in -[types.ts:181](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L181) +[types.ts:183](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L183) ___ @@ -107,7 +119,7 @@ ___ #### Defined in -[types.ts:185](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L185) +[types.ts:187](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L187) ___ @@ -117,7 +129,7 @@ ___ #### Defined in -[types.ts:178](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L178) +[types.ts:180](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L180) ___ @@ -127,7 +139,7 @@ ___ #### Defined in -[types.ts:179](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L179) +[types.ts:181](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L181) ___ @@ -137,7 +149,7 @@ ___ #### Defined in -[types.ts:175](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L175) +[types.ts:177](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L177) ___ @@ -147,7 +159,7 @@ ___ #### Defined in -[types.ts:177](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L177) +[types.ts:179](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L179) ___ @@ -157,7 +169,7 @@ ___ #### Defined in -[types.ts:184](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L184) +[types.ts:186](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L186) ___ @@ -167,7 +179,7 @@ ___ #### Defined in -[types.ts:180](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L180) +[types.ts:182](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L182) ___ @@ -177,7 +189,7 @@ ___ #### Defined in -[types.ts:189](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L189) +[types.ts:191](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L191) ___ @@ -187,7 +199,7 @@ ___ #### Defined in -[types.ts:183](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L183) +[types.ts:185](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L185) ___ @@ -197,7 +209,7 @@ ___ #### Defined in -[types.ts:192](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L192) +[types.ts:194](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L194) ___ @@ -207,7 +219,7 @@ ___ #### Defined in -[types.ts:187](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L187) +[types.ts:189](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L189) ___ @@ -217,7 +229,7 @@ ___ #### Defined in -[types.ts:193](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L193) +[types.ts:195](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L195) ___ @@ -227,7 +239,7 @@ ___ #### Defined in -[types.ts:182](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L182) +[types.ts:184](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L184) ___ @@ -237,7 +249,7 @@ ___ #### Defined in -[types.ts:194](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L194) +[types.ts:196](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L196) ___ @@ -247,4 +259,14 @@ ___ #### Defined in -[types.ts:196](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L196) +[types.ts:198](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L198) + +___ + +### withdrawalsRoot + +• `Optional` **withdrawalsRoot**: `string` + +#### Defined in + +[types.ts:199](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/block/src/types.ts#L199) diff --git a/packages/block/package.json b/packages/block/package.json index e2a91ea7c2..2632b17bbb 100644 --- a/packages/block/package.json +++ b/packages/block/package.json @@ -1,6 +1,6 @@ { "name": "@ethereumjs/block", - "version": "4.2.1", + "version": "4.2.2", "description": "Provides Block serialization and help functions", "keywords": [ "ethereum", @@ -38,11 +38,11 @@ "tsc": "../../config/cli/ts-compile.sh" }, "dependencies": { - "@ethereumjs/common": "^3.1.1", + "@ethereumjs/common": "^3.1.2", "@ethereumjs/rlp": "^4.0.1", - "@ethereumjs/trie": "^5.0.4", - "@ethereumjs/tx": "^4.1.1", - "@ethereumjs/util": "^8.0.5", + "@ethereumjs/trie": "^5.0.5", + "@ethereumjs/tx": "^4.1.2", + "@ethereumjs/util": "^8.0.6", "ethereum-cryptography": "^2.0.0" }, "devDependencies": { diff --git a/packages/blockchain/CHANGELOG.md b/packages/blockchain/CHANGELOG.md index 8d2689e116..991e8a11be 100644 --- a/packages/blockchain/CHANGELOG.md +++ b/packages/blockchain/CHANGELOG.md @@ -6,6 +6,11 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) (modification: no type change headlines) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). +## 6.2.2 - 2023-04-20 + +- Update ethereum-cryptography from 1.2 to 2.0 (switch from noble-secp256k1 to noble-curves), PR [#2641](https://github.com/ethereumjs/ethereumjs-monorepo/pull/2641) +- Bump `@ethereumjs/util` `@chainsafe/ssz` dependency to 0.11.1 (no WASM, native SHA-256 implementation, ES2019 compatible, explicit imports), PRs [#2622](https://github.com/ethereumjs/ethereumjs-monorepo/pull/2622), [#2564](https://github.com/ethereumjs/ethereumjs-monorepo/pull/2564) and [#2656](https://github.com/ethereumjs/ethereumjs-monorepo/pull/2656) + ## 6.2.1 - 2023-02-27 - Pinned `@ethereumjs/util` `@chainsafe/ssz` dependency to `v0.9.4` due to ES2021 features used in `v0.10.+` causing compatibility issues, PR [#2555](https://github.com/ethereumjs/ethereumjs-monorepo/pull/2555) diff --git a/packages/blockchain/docs/classes/Blockchain.md b/packages/blockchain/docs/classes/Blockchain.md index a6a3f990e7..c9f4fd1e23 100644 --- a/packages/blockchain/docs/classes/Blockchain.md +++ b/packages/blockchain/docs/classes/Blockchain.md @@ -109,7 +109,7 @@ The genesis Block for the blockchain. #### Defined in -[blockchain.ts:1298](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/blockchain/src/blockchain.ts#L1298) +[blockchain.ts:1299](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/blockchain/src/blockchain.ts#L1299) ## Methods @@ -181,7 +181,7 @@ Creates a genesis Block for the blockchain with params from Common.genesis #### Defined in -[blockchain.ts:1307](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/blockchain/src/blockchain.ts#L1307) +[blockchain.ts:1308](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/blockchain/src/blockchain.ts#L1308) ___ @@ -235,7 +235,7 @@ All values are provided as hex-prefixed strings. #### Defined in -[blockchain.ts:1341](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/blockchain/src/blockchain.ts#L1341) +[blockchain.ts:1342](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/blockchain/src/blockchain.ts#L1342) ___ @@ -346,7 +346,7 @@ Gets a header by number. Header must be in the canonical chain #### Defined in -[blockchain.ts:1272](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/blockchain/src/blockchain.ts#L1272) +[blockchain.ts:1273](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/blockchain/src/blockchain.ts#L1273) ___ @@ -648,7 +648,7 @@ any other error, this function throws. #### Defined in -[blockchain.ts:1283](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/blockchain/src/blockchain.ts#L1283) +[blockchain.ts:1284](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/blockchain/src/blockchain.ts#L1284) ___ diff --git a/packages/blockchain/package.json b/packages/blockchain/package.json index 737c15ab09..31376d71d1 100644 --- a/packages/blockchain/package.json +++ b/packages/blockchain/package.json @@ -1,6 +1,6 @@ { "name": "@ethereumjs/blockchain", - "version": "6.2.1", + "version": "6.2.2", "description": "A module to store and interact with blocks", "keywords": [ "ethereum", @@ -38,13 +38,13 @@ "tsc": "../../config/cli/ts-compile.sh" }, "dependencies": { - "@ethereumjs/block": "^4.2.1", - "@ethereumjs/common": "^3.1.1", - "@ethereumjs/ethash": "^2.0.4", + "@ethereumjs/block": "^4.2.2", + "@ethereumjs/common": "^3.1.2", + "@ethereumjs/ethash": "^2.0.5", "@ethereumjs/rlp": "^4.0.1", - "@ethereumjs/trie": "^5.0.4", - "@ethereumjs/tx": "^4.1.1", - "@ethereumjs/util": "^8.0.5", + "@ethereumjs/trie": "^5.0.5", + "@ethereumjs/tx": "^4.1.2", + "@ethereumjs/util": "^8.0.6", "debug": "^4.3.3", "ethereum-cryptography": "^2.0.0", "level": "^8.0.0", diff --git a/packages/client/CHANGELOG.md b/packages/client/CHANGELOG.md index c0b6f7916d..b984dd8678 100644 --- a/packages/client/CHANGELOG.md +++ b/packages/client/CHANGELOG.md @@ -6,6 +6,21 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) (modification: no type change headlines) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). +## 0.7.1 - 2023-04-20 + +### Features + +- New `numBlocksPerIteration` option to allow to set the number of blocks executed in bulk, other UX optimizations, PR [#2586](https://github.com/ethereumjs/ethereumjs-monorepo/pull/2586) + +### Bugfixes / Maintenance + +- Stability and reorg improvements regarding safe and finalized blocks, PR [#2585](https://github.com/ethereumjs/ethereumjs-monorepo/pull/2585) +- Beacon sync fixes, PR [#2584](https://github.com/ethereumjs/ethereumjs-monorepo/pull/2584) +- Engine API timestamp checks, PR [#2579](https://github.com/ethereumjs/ethereumjs-monorepo/pull/2579) +- Ensure safe/finalized blocks are part of the canonical chain on Engine API `forkchoiceUpdated`, PR [#2577](https://github.com/ethereumjs/ethereumjs-monorepo/pull/2577) +- Engine API: ensure invalid blockhash status gets reported correctly, PR [#2583](https://github.com/ethereumjs/ethereumjs-monorepo/pull/2583) +- Turn off libp2p transport by default, PR [#2557](https://github.com/ethereumjs/ethereumjs-monorepo/pull/2557) + ## 0.7.0 - 2023-02-16 This client release comes with finalized `Shanghai` hardfork support, fully integrates with a (non final) version of `EIP-4844` and allows to setup and run respective testnets, substantially improves on post-Merge UX and comes with a ton of bugfixes and (robustness) improvements being done during January 2023 core dev interop in Austria. So we felt this to be worth a minor version bump! 🙂 🎉 ❤️ diff --git a/packages/client/package.json b/packages/client/package.json index a20e949c01..aa4f740f49 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -1,6 +1,6 @@ { "name": "@ethereumjs/client", - "version": "0.7.0", + "version": "0.7.1", "description": "EthereumJS client implementation", "keywords": [ "ethereum", @@ -58,18 +58,18 @@ }, "dependencies": { "@chainsafe/libp2p-noise": "^4.1.1", - "@ethereumjs/block": "4.2.1", - "@ethereumjs/blockchain": "6.2.1", - "@ethereumjs/common": "3.1.1", - "@ethereumjs/devp2p": "5.1.1", - "@ethereumjs/ethash": "2.0.4", - "@ethereumjs/evm": "1.3.1", + "@ethereumjs/block": "4.2.2", + "@ethereumjs/blockchain": "6.2.2", + "@ethereumjs/common": "3.1.2", + "@ethereumjs/devp2p": "5.1.2", + "@ethereumjs/ethash": "2.0.5", + "@ethereumjs/evm": "1.3.2", "@ethereumjs/rlp": "4.0.1", - "@ethereumjs/statemanager": "1.0.4", - "@ethereumjs/trie": "5.0.4", - "@ethereumjs/tx": "4.1.1", - "@ethereumjs/util": "8.0.5", - "@ethereumjs/vm": "6.4.1", + "@ethereumjs/statemanager": "1.0.5", + "@ethereumjs/trie": "5.0.5", + "@ethereumjs/tx": "4.1.2", + "@ethereumjs/util": "8.0.6", + "@ethereumjs/vm": "6.4.2", "abstract-level": "^1.0.3", "body-parser": "^1.19.2", "c-kzg": "^2.0.4", diff --git a/packages/common/CHANGELOG.md b/packages/common/CHANGELOG.md index bb76cd6daa..5935a15ea2 100644 --- a/packages/common/CHANGELOG.md +++ b/packages/common/CHANGELOG.md @@ -6,6 +6,12 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) (modification: no type change headlines) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). +## 3.1.2 - 2023-04-20 + +- Schedule Shanghai block on mainnet, PR [#2591](https://github.com/ethereumjs/ethereumjs-monorepo/pull/2591) +- Remove and replace some EF bootnodes for `mainnet`, PR [#2576](https://github.com/ethereumjs/ethereumjs-monorepo/pull/2576) +- Bump `@ethereumjs/util` `@chainsafe/ssz` dependency to 0.11.1 (no WASM, native SHA-256 implementation, ES2019 compatible, explicit imports), PRs [#2622](https://github.com/ethereumjs/ethereumjs-monorepo/pull/2622), [#2564](https://github.com/ethereumjs/ethereumjs-monorepo/pull/2564) and [#2656](https://github.com/ethereumjs/ethereumjs-monorepo/pull/2656) + ## 3.1.1 - 2023-02-27 - Pinned `@ethereumjs/util` `@chainsafe/ssz` dependency to `v0.9.4` due to ES2021 features used in `v0.10.+` causing compatibility issues, PR [#2555](https://github.com/ethereumjs/ethereumjs-monorepo/pull/2555) diff --git a/packages/common/docs/README.md b/packages/common/docs/README.md index f0c0fbe880..91d7dd443d 100644 --- a/packages/common/docs/README.md +++ b/packages/common/docs/README.md @@ -118,4 +118,4 @@ parsed params #### Defined in -[packages/common/src/utils.ts:207](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/common/src/utils.ts#L207) +[packages/common/src/utils.ts:196](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/common/src/utils.ts#L196) diff --git a/packages/common/package.json b/packages/common/package.json index 4c4dcd0005..c59413a432 100644 --- a/packages/common/package.json +++ b/packages/common/package.json @@ -1,6 +1,6 @@ { "name": "@ethereumjs/common", - "version": "3.1.1", + "version": "3.1.2", "description": "Resources common to all Ethereum implementations", "keywords": [ "ethereum", @@ -48,7 +48,7 @@ "tsc": "../../config/cli/ts-compile.sh" }, "dependencies": { - "@ethereumjs/util": "^8.0.5", + "@ethereumjs/util": "^8.0.6", "crc-32": "^1.2.0" } } diff --git a/packages/devp2p/CHANGELOG.md b/packages/devp2p/CHANGELOG.md index 14797811cf..8ac8cc65aa 100644 --- a/packages/devp2p/CHANGELOG.md +++ b/packages/devp2p/CHANGELOG.md @@ -6,6 +6,11 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) (modification: no type change headlines) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). +## 5.1.2 - 2023-04-20 + +- Update ethereum-cryptography from 1.2 to 2.0 (switch from noble-secp256k1 to noble-curves), PR [#2641](https://github.com/ethereumjs/ethereumjs-monorepo/pull/2641) +- Bump `@ethereumjs/util` `@chainsafe/ssz` dependency to 0.11.1 (no WASM, native SHA-256 implementation, ES2019 compatible, explicit imports), PRs [#2622](https://github.com/ethereumjs/ethereumjs-monorepo/pull/2622), [#2564](https://github.com/ethereumjs/ethereumjs-monorepo/pull/2564) and [#2656](https://github.com/ethereumjs/ethereumjs-monorepo/pull/2656) + ## 5.1.1 - 2023-02-27 - Pinned `@ethereumjs/util` `@chainsafe/ssz` dependency to `v0.9.4` due to ES2021 features used in `v0.10.+` causing compatibility issues, PR [#2555](https://github.com/ethereumjs/ethereumjs-monorepo/pull/2555) diff --git a/packages/devp2p/package.json b/packages/devp2p/package.json index 3664f7a678..5252a8f814 100644 --- a/packages/devp2p/package.json +++ b/packages/devp2p/package.json @@ -1,6 +1,6 @@ { "name": "@ethereumjs/devp2p", - "version": "5.1.1", + "version": "5.1.2", "description": "A JavaScript implementation of ÐΞVp2p", "keywords": [ "ethereum", @@ -49,9 +49,9 @@ "tsc": "../../config/cli/ts-compile.sh" }, "dependencies": { - "@ethereumjs/common": "^3.1.1", + "@ethereumjs/common": "^3.1.2", "@ethereumjs/rlp": "^4.0.1", - "@ethereumjs/util": "^8.0.5", + "@ethereumjs/util": "^8.0.6", "@scure/base": "1.1.1", "@types/k-bucket": "^5.0.0", "debug": "^4.3.3", @@ -64,8 +64,8 @@ "snappyjs": "^0.6.1" }, "devDependencies": { - "@ethereumjs/block": "^4.2.1", - "@ethereumjs/tx": "^4.1.1", + "@ethereumjs/block": "^4.2.2", + "@ethereumjs/tx": "^4.1.2", "@types/chalk": "^2.2.0", "@types/debug": "^4.1.4", "@types/ip": "^1.1.0", diff --git a/packages/ethash/CHANGELOG.md b/packages/ethash/CHANGELOG.md index 50ae062b36..422c5b4f14 100644 --- a/packages/ethash/CHANGELOG.md +++ b/packages/ethash/CHANGELOG.md @@ -6,6 +6,11 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) (modification: no type change headlines) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). +## 2.0.5 - 2023-04-30 + +- Update ethereum-cryptography from 1.2 to 2.0 (switch from noble-secp256k1 to noble-curves), PR [#2641](https://github.com/ethereumjs/ethereumjs-monorepo/pull/2641) +- Bump `@ethereumjs/util` `@chainsafe/ssz` dependency to 0.11.1 (no WASM, native SHA-256 implementation, ES2019 compatible, explicit imports), PRs [#2622](https://github.com/ethereumjs/ethereumjs-monorepo/pull/2622), [#2564](https://github.com/ethereumjs/ethereumjs-monorepo/pull/2564) and [#2656](https://github.com/ethereumjs/ethereumjs-monorepo/pull/2656) + ## 2.0.4 - 2023-02-27 - Pinned `@ethereumjs/util` `@chainsafe/ssz` dependency to `v0.9.4` due to ES2021 features used in `v0.10.+` causing compatibility issues, PR [#2555](https://github.com/ethereumjs/ethereumjs-monorepo/pull/2555) diff --git a/packages/ethash/package.json b/packages/ethash/package.json index f2d1bf4068..61b03a0b85 100644 --- a/packages/ethash/package.json +++ b/packages/ethash/package.json @@ -1,6 +1,6 @@ { "name": "@ethereumjs/ethash", - "version": "2.0.4", + "version": "2.0.5", "description": "An ethash implementation in JavaScript", "keywords": [ "ethash", @@ -37,14 +37,14 @@ "tsc": "../../config/cli/ts-compile.sh" }, "dependencies": { - "@ethereumjs/block": "^4.2.1", + "@ethereumjs/block": "^4.2.2", "@ethereumjs/rlp": "^4.0.1", - "@ethereumjs/util": "^8.0.5", + "@ethereumjs/util": "^8.0.6", "bigint-crypto-utils": "^3.2.2", "ethereum-cryptography": "^2.0.0" }, "devDependencies": { - "@ethereumjs/common": "^3.1.1" + "@ethereumjs/common": "^3.1.2" }, "engines": { "node": ">=16" diff --git a/packages/evm/CHANGELOG.md b/packages/evm/CHANGELOG.md index 709d8f1966..ba6e258ce7 100644 --- a/packages/evm/CHANGELOG.md +++ b/packages/evm/CHANGELOG.md @@ -6,6 +6,30 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) (modification: no type change headlines) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). +## 1.3.2 - 2023-04-20 + +### Features + +- Add `allowUnlimitedInitcodeSize` option to partially disable EIP-3860, PR [#2594](https://github.com/ethereumjs/ethereumjs-monorepo/pull/2594) + +### Bugfixes + +- Fixed `EIP-3860` (max init code size) for CREATE and CREATE2, PR [#2601](https://github.com/ethereumjs/ethereumjs-monorepo/pull/2601) +- Fixed block hash calculation when creating a new block object From JSON RPC (Shanghai), PR [#2600](https://github.com/ethereumjs/ethereumjs-monorepo/pull/2600) +- Fix `memory` in `step` event to report the actual memory which the EVM sees, PR [#2598](https://github.com/ethereumjs/ethereumjs-monorepo/pull/2598) + +### Performance + +- Avoid memory.read() Memory Copy (performance), PR [#2573](https://github.com/ethereumjs/ethereumjs-monorepo/pull/2573) +- Memory Fix & selected performance optimizations, PR [#2570](https://github.com/ethereumjs/ethereumjs-monorepo/pull/2570) +- `bnadd`/`bnmul` Precompile Performance Optimization, PR [#2568](https://github.com/ethereumjs/ethereumjs-monorepo/pull/2568) + +### Maintenance + +- Update ethereum-cryptography from 1.2 to 2.0 (switch from noble-secp256k1 to noble-curves), PR [#2641](https://github.com/ethereumjs/ethereumjs-monorepo/pull/2641) +- Bump `@ethereumjs/util` `@chainsafe/ssz` dependency to 0.11.1 (no WASM, native SHA-256 implementation, ES2019 compatible, explicit imports), PRs [#2622](https://github.com/ethereumjs/ethereumjs-monorepo/pull/2622), [#2564](https://github.com/ethereumjs/ethereumjs-monorepo/pull/2564) and [#2656](https://github.com/ethereumjs/ethereumjs-monorepo/pull/2656) +- Precompile Debug Logger Improvements, PR [#2572](https://github.com/ethereumjs/ethereumjs-monorepo/pull/2572) + ## 1.3.1 - 2023-02-27 - Pinned `@ethereumjs/util` `@chainsafe/ssz` dependency to `v0.9.4` due to ES2021 features used in `v0.10.+` causing compatibility issues, PR [#2555](https://github.com/ethereumjs/ethereumjs-monorepo/pull/2555) diff --git a/packages/evm/docs/interfaces/EVMResult.md b/packages/evm/docs/interfaces/EVMResult.md index ba78cc3369..3e01acfba2 100644 --- a/packages/evm/docs/interfaces/EVMResult.md +++ b/packages/evm/docs/interfaces/EVMResult.md @@ -21,7 +21,7 @@ Address of created account during transaction, if any #### Defined in -[evm.ts:968](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/evm/src/evm.ts#L968) +[evm.ts:971](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/evm/src/evm.ts#L971) ___ @@ -33,4 +33,4 @@ Contains the results from running the code, if any, as described in runCode #### Defined in -[evm.ts:972](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/evm/src/evm.ts#L972) +[evm.ts:975](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/evm/src/evm.ts#L975) diff --git a/packages/evm/docs/interfaces/ExecResult.md b/packages/evm/docs/interfaces/ExecResult.md index e3d3689cfa..88250ee1ff 100644 --- a/packages/evm/docs/interfaces/ExecResult.md +++ b/packages/evm/docs/interfaces/ExecResult.md @@ -27,7 +27,7 @@ Description of the exception, if any occurred #### Defined in -[evm.ts:983](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/evm/src/evm.ts#L983) +[evm.ts:986](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/evm/src/evm.ts#L986) ___ @@ -39,7 +39,7 @@ Amount of gas the code used to run #### Defined in -[evm.ts:991](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/evm/src/evm.ts#L991) +[evm.ts:994](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/evm/src/evm.ts#L994) ___ @@ -51,7 +51,7 @@ Amount of gas left #### Defined in -[evm.ts:987](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/evm/src/evm.ts#L987) +[evm.ts:990](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/evm/src/evm.ts#L990) ___ @@ -63,7 +63,7 @@ The gas refund counter #### Defined in -[evm.ts:1007](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/evm/src/evm.ts#L1007) +[evm.ts:1010](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/evm/src/evm.ts#L1010) ___ @@ -75,7 +75,7 @@ Array of logs that the contract emitted #### Defined in -[evm.ts:999](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/evm/src/evm.ts#L999) +[evm.ts:1002](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/evm/src/evm.ts#L1002) ___ @@ -87,7 +87,7 @@ Return value from the contract #### Defined in -[evm.ts:995](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/evm/src/evm.ts#L995) +[evm.ts:998](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/evm/src/evm.ts#L998) ___ @@ -97,7 +97,7 @@ ___ #### Defined in -[evm.ts:979](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/evm/src/evm.ts#L979) +[evm.ts:982](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/evm/src/evm.ts#L982) ___ @@ -113,4 +113,4 @@ A map from the accounts that have self-destructed to the addresses to send their #### Defined in -[evm.ts:1003](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/evm/src/evm.ts#L1003) +[evm.ts:1006](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/evm/src/evm.ts#L1006) diff --git a/packages/evm/package.json b/packages/evm/package.json index f1ac7cef61..0b4712d2c7 100644 --- a/packages/evm/package.json +++ b/packages/evm/package.json @@ -1,6 +1,6 @@ { "name": "@ethereumjs/evm", - "version": "1.3.1", + "version": "1.3.2", "description": "JavaScript Ethereum Virtual Machine (EVM) implementation", "keywords": [ "ethereum", @@ -47,17 +47,17 @@ "tsc": "../../config/cli/ts-compile.sh" }, "dependencies": { - "@ethereumjs/statemanager": "^1.0.4", - "@ethereumjs/common": "^3.1.1", - "@ethereumjs/util": "^8.0.5", + "@ethereumjs/common": "^3.1.2", + "@ethereumjs/tx": "^4.1.2", + "@ethereumjs/util": "^8.0.6", "debug": "^4.3.3", "ethereum-cryptography": "^2.0.0", "mcl-wasm": "^0.7.1", "rustbn.js": "~0.2.0" }, "devDependencies": { + "@ethereumjs/statemanager": "^1.0.5", "@ethersproject/abi": "^5.0.12", - "@ethereumjs/statemanager": "^1.0.4", "@types/benchmark": "^1.0.33", "@types/core-js": "^2.5.0", "@types/minimist": "^1.2.2", diff --git a/packages/statemanager/CHANGELOG.md b/packages/statemanager/CHANGELOG.md index b604bbc13f..d5cf35ab96 100644 --- a/packages/statemanager/CHANGELOG.md +++ b/packages/statemanager/CHANGELOG.md @@ -6,6 +6,11 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) (modification: no type change headlines) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). +## 1.0.5 - 2023-04-20 + +- Update ethereum-cryptography from 1.2 to 2.0 (switch from noble-secp256k1 to noble-curves), PR [#2641](https://github.com/ethereumjs/ethereumjs-monorepo/pull/2641) +- Bump `@ethereumjs/util` `@chainsafe/ssz` dependency to 0.11.1 (no WASM, native SHA-256 implementation, ES2019 compatible, explicit imports), PRs [#2622](https://github.com/ethereumjs/ethereumjs-monorepo/pull/2622), [#2564](https://github.com/ethereumjs/ethereumjs-monorepo/pull/2564) and [#2656](https://github.com/ethereumjs/ethereumjs-monorepo/pull/2656) + ## 1.0.4 - 2023-02-27 - Pinned `@ethereumjs/util` `@chainsafe/ssz` dependency to `v0.9.4` due to ES2021 features used in `v0.10.+` causing compatibility issues, PR [#2555](https://github.com/ethereumjs/ethereumjs-monorepo/pull/2555) diff --git a/packages/statemanager/docs/README.md b/packages/statemanager/docs/README.md index 70a10a1d64..8561754233 100644 --- a/packages/statemanager/docs/README.md +++ b/packages/statemanager/docs/README.md @@ -21,6 +21,10 @@ - [AccountFields](README.md#accountfields) - [Proof](README.md#proof) +### Variables + +- [CODEHASH\_PREFIX](README.md#codehash_prefix) + ## Type Aliases ### AccountFields @@ -52,3 +56,20 @@ ___ #### Defined in [stateManager.ts:29](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/statemanager/src/stateManager.ts#L29) + +## Variables + +### CODEHASH\_PREFIX + +• `Const` **CODEHASH\_PREFIX**: `Buffer` + +Prefix to distinguish between a contract deployed with code `0x80` +and `RLP([])` (also having the value `0x80`). + +Otherwise the creation of the code hash for the `0x80` contract +will be the same as the hash of the empty trie which leads to +misbehaviour in the underlying trie library. + +#### Defined in + +[stateManager.ts:47](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/statemanager/src/stateManager.ts#L47) diff --git a/packages/statemanager/package.json b/packages/statemanager/package.json index 67f3491682..310e70d649 100644 --- a/packages/statemanager/package.json +++ b/packages/statemanager/package.json @@ -1,6 +1,6 @@ { "name": "@ethereumjs/statemanager", - "version": "1.0.4", + "version": "1.0.5", "description": "An Ethereum statemanager implementation", "keywords": [ "ethereum", @@ -41,7 +41,7 @@ "tsc": "../../config/cli/ts-compile.sh" }, "dependencies": { - "@ethereumjs/common": "^3.1.1", + "@ethereumjs/common": "^3.1.2", "@ethereumjs/rlp": "^4.0.1", "debug": "^4.3.3", "ethereum-cryptography": "^2.0.0", @@ -50,9 +50,9 @@ "lru-cache": "^7.18.3" }, "devDependencies": { - "@ethereumjs/block": "^4.2.1", - "@ethereumjs/trie": "^5.0.4", - "@ethereumjs/util": "^8.0.5", + "@ethereumjs/block": "^4.2.2", + "@ethereumjs/trie": "^5.0.5", + "@ethereumjs/util": "^8.0.6", "@types/node": "^16.11.7", "@types/tape": "^4.13.2", "debug": "^4.3.3", diff --git a/packages/trie/CHANGELOG.md b/packages/trie/CHANGELOG.md index 5b95497b97..45e2546364 100644 --- a/packages/trie/CHANGELOG.md +++ b/packages/trie/CHANGELOG.md @@ -6,6 +6,11 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) (modification: no type change headlines) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). +## 5.0.5 - 2023-04-20 + +- Update ethereum-cryptography from 1.2 to 2.0 (switch from noble-secp256k1 to noble-curves), PR [#2641](https://github.com/ethereumjs/ethereumjs-monorepo/pull/2641) +- Bump `@ethereumjs/util` `@chainsafe/ssz` dependency to 0.11.1 (no WASM, native SHA-256 implementation, ES2019 compatible, explicit imports), PRs [#2622](https://github.com/ethereumjs/ethereumjs-monorepo/pull/2622), [#2564](https://github.com/ethereumjs/ethereumjs-monorepo/pull/2564) and [#2656](https://github.com/ethereumjs/ethereumjs-monorepo/pull/2656) + ## 5.0.4 - 2023-02-27 - Pinned `@ethereumjs/util` `@chainsafe/ssz` dependency to `v0.9.4` due to ES2021 features used in `v0.10.+` causing compatibility issues, PR [#2555](https://github.com/ethereumjs/ethereumjs-monorepo/pull/2555) diff --git a/packages/trie/package.json b/packages/trie/package.json index 135c2d84ec..f52ad7f531 100644 --- a/packages/trie/package.json +++ b/packages/trie/package.json @@ -1,6 +1,6 @@ { "name": "@ethereumjs/trie", - "version": "5.0.4", + "version": "5.0.5", "description": "This is an implementation of the modified merkle patricia tree as specified in Ethereum's yellow paper.", "keywords": [ "merkle", @@ -46,7 +46,7 @@ }, "dependencies": { "@ethereumjs/rlp": "^4.0.1", - "@ethereumjs/util": "^8.0.5", + "@ethereumjs/util": "^8.0.6", "@types/readable-stream": "^2.3.13", "lru-cache": "^7.18.3", "ethereum-cryptography": "^2.0.0", diff --git a/packages/tx/CHANGELOG.md b/packages/tx/CHANGELOG.md index dc03d8695e..9730e1ae6a 100644 --- a/packages/tx/CHANGELOG.md +++ b/packages/tx/CHANGELOG.md @@ -6,6 +6,24 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) (modification: no type change headlines) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). +## 4.1.2 - 2023-04-20 + +### Features + +- Add `allowUnlimitedInitcodeSize` option to partially disable EIP-3860, PR [#2594](https://github.com/ethereumjs/ethereumjs-monorepo/pull/2594) +- Better Optimism RPC compatibility, new `TransactionFactory.fromRPCTx()` static constructor, PR [#2613](https://github.com/ethereumjs/ethereumjs-monorepo/pull/2613) + +### Bugfixes + +- Fixed EIP-3860 (max init code size) check when deserializing RLPs, PR [#2601](https://github.com/ethereumjs/ethereumjs-monorepo/pull/2601) +- EIP-3860: only check max init code size on create contract tx, PR [#2575](https://github.com/ethereumjs/ethereumjs-monorepo/pull/2575) + +### Maintenance + +- Removed `Ethers` dependency, alternative `fromEthersProvider()` static constructor implementation, PR [#2633](https://github.com/ethereumjs/ethereumjs-monorepo/pull/2633) +- Bump `@ethereumjs/util` `@chainsafe/ssz` dependency to 0.11.1 (no WASM, native SHA-256 implementation, ES2019 compatible, explicit imports), PRs [#2622](https://github.com/ethereumjs/ethereumjs-monorepo/pull/2622), [#2564](https://github.com/ethereumjs/ethereumjs-monorepo/pull/2564) and [#2656](https://github.com/ethereumjs/ethereumjs-monorepo/pull/2656) +- Update ethereum-cryptography from 1.2 to 2.0 (switch from noble-secp256k1 to noble-curves), PR [#2641](https://github.com/ethereumjs/ethereumjs-monorepo/pull/2641) + ## 4.1.1 - 2023-02-27 - Pinned `@ethereumjs/util` `@chainsafe/ssz` dependency to `v0.9.4` due to ES2021 features used in `v0.10.+` causing compatibility issues, PR [#2555](https://github.com/ethereumjs/ethereumjs-monorepo/pull/2555) diff --git a/packages/tx/docs/README.md b/packages/tx/docs/README.md index b2b7e7d160..3eb948b76a 100644 --- a/packages/tx/docs/README.md +++ b/packages/tx/docs/README.md @@ -11,6 +11,7 @@ ### Classes - [AccessListEIP2930Transaction](classes/AccessListEIP2930Transaction.md) +- [BlobEIP4844Transaction](classes/BlobEIP4844Transaction.md) - [FeeMarketEIP1559Transaction](classes/FeeMarketEIP1559Transaction.md) - [Transaction](classes/Transaction.md) - [TransactionFactory](classes/TransactionFactory.md) @@ -18,6 +19,7 @@ ### Interfaces - [AccessListEIP2930TxData](interfaces/AccessListEIP2930TxData.md) +- [BlobEIP4844TxData](interfaces/BlobEIP4844TxData.md) - [FeeMarketEIP1559TxData](interfaces/FeeMarketEIP1559TxData.md) - [JsonRpcTx](interfaces/JsonRpcTx.md) - [JsonTx](interfaces/JsonTx.md) @@ -35,8 +37,22 @@ - [TxValuesArray](README.md#txvaluesarray) - [TypedTransaction](README.md#typedtransaction) +### Variables + +- [AccessTupleType](README.md#accesstupletype) +- [AddressType](README.md#addresstype) +- [BlobNetworkTransactionWrapper](README.md#blobnetworktransactionwrapper) +- [BlobTransactionType](README.md#blobtransactiontype) +- [ECDSASignatureType](README.md#ecdsasignaturetype) +- [KZGCommitmentType](README.md#kzgcommitmenttype) +- [KZGProofType](README.md#kzgprooftype) +- [SignedBlobTransactionType](README.md#signedblobtransactiontype) +- [kzg](README.md#kzg) + ### Functions +- [computeVersionedHash](README.md#computeversionedhash) +- [initKZG](README.md#initkzg) - [isAccessList](README.md#isaccesslist) - [isAccessListBuffer](README.md#isaccesslistbuffer) @@ -48,7 +64,7 @@ #### Defined in -[types.ts:80](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L80) +[types.ts:115](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L115) ___ @@ -58,7 +74,7 @@ ___ #### Defined in -[types.ts:79](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L79) +[types.ts:114](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L114) ___ @@ -68,7 +84,7 @@ ___ #### Defined in -[types.ts:78](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L78) +[types.ts:113](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L113) ___ @@ -80,7 +96,7 @@ Buffer values array for an [AccessListEIP2930Transaction](classes/AccessListEIP2 #### Defined in -[types.ts:208](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L208) +[types.ts:270](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L270) ___ @@ -97,7 +113,7 @@ ___ #### Defined in -[types.ts:70](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L70) +[types.ts:105](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L105) ___ @@ -109,7 +125,7 @@ Buffer values array for a [FeeMarketEIP1559Transaction](classes/FeeMarketEIP1559 #### Defined in -[types.ts:225](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L225) +[types.ts:287](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L287) ___ @@ -125,7 +141,7 @@ Legacy [Transaction](classes/Transaction.md) Data | :------ | :------ | :------ | | `data?` | `BufferLike` | This will contain the data of the message or the init of a contract. | | `gasLimit?` | `BigIntLike` | The transaction's gas limit. | -| `gasPrice?` | `BigIntLike` | The transaction's gas price. | +| `gasPrice?` | `BigIntLike` \| ``null`` | The transaction's gas price. | | `nonce?` | `BigIntLike` | The transaction's nonce. | | `r?` | `BigIntLike` | EC signature parameter. | | `s?` | `BigIntLike` | EC signature parameter. | @@ -136,7 +152,7 @@ Legacy [Transaction](classes/Transaction.md) Data #### Defined in -[types.ts:113](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L113) +[types.ts:149](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L149) ___ @@ -148,13 +164,13 @@ Buffer values array for a legacy [Transaction](classes/Transaction.md) #### Defined in -[types.ts:203](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L203) +[types.ts:265](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L265) ___ ### TypedTransaction -Ƭ **TypedTransaction**: [`Transaction`](classes/Transaction.md) \| [`AccessListEIP2930Transaction`](classes/AccessListEIP2930Transaction.md) \| [`FeeMarketEIP1559Transaction`](classes/FeeMarketEIP1559Transaction.md) +Ƭ **TypedTransaction**: [`Transaction`](classes/Transaction.md) \| [`AccessListEIP2930Transaction`](classes/AccessListEIP2930Transaction.md) \| [`FeeMarketEIP1559Transaction`](classes/FeeMarketEIP1559Transaction.md) \| [`BlobEIP4844Transaction`](classes/BlobEIP4844Transaction.md) Encompassing type for all transaction types. @@ -163,10 +179,150 @@ referenced as [Transaction](classes/Transaction.md) for compatibility reasons. #### Defined in -[types.ts:105](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L105) +[types.ts:140](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L140) + +## Variables + +### AccessTupleType + +• `Const` **AccessTupleType**: `ContainerType`<{ `address`: `ByteVectorType` = AddressType; `storageKeys`: `ListCompositeType`<`ByteVectorType`\> }\> + +#### Defined in + +[types.ts:362](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L362) + +___ + +### AddressType + +• `Const` **AddressType**: `ByteVectorType` = `Bytes20` + +EIP4844 types + +#### Defined in + +[types.ts:359](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L359) + +___ + +### BlobNetworkTransactionWrapper + +• `Const` **BlobNetworkTransactionWrapper**: `ContainerType`<{ `blobKzgs`: `ListCompositeType`<`ByteVectorType`\> ; `blobs`: `ListCompositeType`<`ByteVectorType`\> ; `kzgAggregatedProof`: `ByteVectorType` = KZGProofType; `tx`: `ContainerType`<{ `message`: `ContainerType`<{ `accessList`: `ListCompositeType`<`ContainerType`<{ `address`: `ByteVectorType` = AddressType; `storageKeys`: `ListCompositeType`<`ByteVectorType`\> }\>\> ; `blobVersionedHashes`: `ListCompositeType`<`ByteVectorType`\> ; `chainId`: `UintBigintType` = Uint256; `data`: `ByteListType` ; `gas`: `UintBigintType` = Uint64; `maxFeePerDataGas`: `UintBigintType` = Uint256; `maxFeePerGas`: `UintBigintType` = Uint256; `maxPriorityFeePerGas`: `UintBigintType` = Uint256; `nonce`: `UintBigintType` = Uint64; `to`: `UnionType`<(`ByteVectorType` \| `NoneType`)[]\> ; `value`: `UintBigintType` = Uint256 }\> = BlobTransactionType; `signature`: `ContainerType`<{ `r`: `UintBigintType` = Uint256; `s`: `UintBigintType` = Uint256; `yParity`: `BooleanType` }\> = ECDSASignatureType }\> = SignedBlobTransactionType }\> + +#### Defined in + +[types.ts:400](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L400) + +___ + +### BlobTransactionType + +• `Const` **BlobTransactionType**: `ContainerType`<{ `accessList`: `ListCompositeType`<`ContainerType`<{ `address`: `ByteVectorType` = AddressType; `storageKeys`: `ListCompositeType`<`ByteVectorType`\> }\>\> ; `blobVersionedHashes`: `ListCompositeType`<`ByteVectorType`\> ; `chainId`: `UintBigintType` = Uint256; `data`: `ByteListType` ; `gas`: `UintBigintType` = Uint64; `maxFeePerDataGas`: `UintBigintType` = Uint256; `maxFeePerGas`: `UintBigintType` = Uint256; `maxPriorityFeePerGas`: `UintBigintType` = Uint256; `nonce`: `UintBigintType` = Uint64; `to`: `UnionType`<(`ByteVectorType` \| `NoneType`)[]\> ; `value`: `UintBigintType` = Uint256 }\> + +#### Defined in + +[types.ts:368](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L368) + +___ + +### ECDSASignatureType + +• `Const` **ECDSASignatureType**: `ContainerType`<{ `r`: `UintBigintType` = Uint256; `s`: `UintBigintType` = Uint256; `yParity`: `BooleanType` }\> + +#### Defined in + +[types.ts:383](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L383) + +___ + +### KZGCommitmentType + +• `Const` **KZGCommitmentType**: `ByteVectorType` = `Bytes48` + +#### Defined in + +[types.ts:396](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L396) + +___ + +### KZGProofType + +• `Const` **KZGProofType**: `ByteVectorType` = `KZGCommitmentType` + +#### Defined in + +[types.ts:397](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L397) + +___ + +### SignedBlobTransactionType + +• `Const` **SignedBlobTransactionType**: `ContainerType`<{ `message`: `ContainerType`<{ `accessList`: `ListCompositeType`<`ContainerType`<{ `address`: `ByteVectorType` = AddressType; `storageKeys`: `ListCompositeType`<`ByteVectorType`\> }\>\> ; `blobVersionedHashes`: `ListCompositeType`<`ByteVectorType`\> ; `chainId`: `UintBigintType` = Uint256; `data`: `ByteListType` ; `gas`: `UintBigintType` = Uint64; `maxFeePerDataGas`: `UintBigintType` = Uint256; `maxFeePerGas`: `UintBigintType` = Uint256; `maxPriorityFeePerGas`: `UintBigintType` = Uint256; `nonce`: `UintBigintType` = Uint64; `to`: `UnionType`<(`ByteVectorType` \| `NoneType`)[]\> ; `value`: `UintBigintType` = Uint256 }\> = BlobTransactionType; `signature`: `ContainerType`<{ `r`: `UintBigintType` = Uint256; `s`: `UintBigintType` = Uint256; `yParity`: `BooleanType` }\> = ECDSASignatureType }\> + +#### Defined in + +[types.ts:390](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L390) + +___ + +### kzg + +• **kzg**: `Kzg` + +#### Defined in + +[kzg/kzg.ts:8](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/kzg/kzg.ts#L8) ## Functions +### computeVersionedHash + +▸ **computeVersionedHash**(`commitment`, `blobCommitmentVersion`): `Uint8Array` + +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 +types are introduced + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `commitment` | `Uint8Array` | a vector commitment to a blob | +| `blobCommitmentVersion` | `number` | the version number corresponding to the type of vector commitment | + +#### Returns + +`Uint8Array` + +a versioned hash corresponding to a given blob vector commitment + +#### Defined in + +[utils/blobHelpers.ts:74](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/utils/blobHelpers.ts#L74) + +___ + +### initKZG + +▸ **initKZG**(`kzgLib`, `trustedSetupPath`): `void` + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `kzgLib` | `Kzg` | a KZG implementation (defaults to c-kzg) | +| `trustedSetupPath` | `string` | the full path (e.g. "/home/linux/devnet4.txt") to a kzg trusted setup text file | + +#### Returns + +`void` + +#### Defined in + +[kzg/kzg.ts:21](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/kzg/kzg.ts#L21) + +___ + ### isAccessList ▸ **isAccessList**(`input`): input is AccessList @@ -183,7 +339,7 @@ input is AccessList #### Defined in -[types.ts:95](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L95) +[types.ts:130](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L130) ___ @@ -203,4 +359,4 @@ input is AccessListBuffer #### Defined in -[types.ts:82](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L82) +[types.ts:117](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L117) diff --git a/packages/tx/docs/classes/AccessListEIP2930Transaction.md b/packages/tx/docs/classes/AccessListEIP2930Transaction.md index 15c88c847d..40b41a522d 100644 --- a/packages/tx/docs/classes/AccessListEIP2930Transaction.md +++ b/packages/tx/docs/classes/AccessListEIP2930Transaction.md @@ -147,7 +147,7 @@ BaseTransaction.data #### Defined in -[baseTransaction.ts:51](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L51) +[baseTransaction.ts:52](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L52) ___ @@ -161,7 +161,7 @@ BaseTransaction.gasLimit #### Defined in -[baseTransaction.ts:48](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L48) +[baseTransaction.ts:49](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L49) ___ @@ -185,7 +185,7 @@ BaseTransaction.nonce #### Defined in -[baseTransaction.ts:47](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L47) +[baseTransaction.ts:48](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L48) ___ @@ -199,7 +199,7 @@ BaseTransaction.r #### Defined in -[baseTransaction.ts:54](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L54) +[baseTransaction.ts:55](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L55) ___ @@ -213,7 +213,7 @@ BaseTransaction.s #### Defined in -[baseTransaction.ts:55](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L55) +[baseTransaction.ts:56](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L56) ___ @@ -227,7 +227,7 @@ BaseTransaction.to #### Defined in -[baseTransaction.ts:49](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L49) +[baseTransaction.ts:50](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L50) ___ @@ -241,7 +241,7 @@ BaseTransaction.v #### Defined in -[baseTransaction.ts:53](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L53) +[baseTransaction.ts:54](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L54) ___ @@ -255,7 +255,7 @@ BaseTransaction.value #### Defined in -[baseTransaction.ts:50](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L50) +[baseTransaction.ts:51](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L51) ## Accessors @@ -277,7 +277,7 @@ BaseTransaction.type #### Defined in -[baseTransaction.ts:126](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L126) +[baseTransaction.ts:134](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L134) ## Methods @@ -303,7 +303,7 @@ BaseTransaction.\_processSignature #### Defined in -[eip2930Transaction.ts:338](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/eip2930Transaction.ts#L338) +[eip2930Transaction.ts:335](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/eip2930Transaction.ts#L335) ___ @@ -323,7 +323,7 @@ BaseTransaction.errorStr #### Defined in -[eip2930Transaction.ts:383](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/eip2930Transaction.ts#L383) +[eip2930Transaction.ts:380](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/eip2930Transaction.ts#L380) ___ @@ -343,7 +343,7 @@ BaseTransaction.getBaseFee #### Defined in -[baseTransaction.ts:196](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L196) +[baseTransaction.ts:204](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L204) ___ @@ -363,7 +363,7 @@ BaseTransaction.getDataFee #### Defined in -[eip2930Transaction.ts:184](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/eip2930Transaction.ts#L184) +[eip2930Transaction.ts:181](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/eip2930Transaction.ts#L181) ___ @@ -397,7 +397,7 @@ BaseTransaction.getMessageToSign #### Defined in -[eip2930Transaction.ts:269](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/eip2930Transaction.ts#L269) +[eip2930Transaction.ts:266](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/eip2930Transaction.ts#L266) ___ @@ -417,7 +417,7 @@ BaseTransaction.getMessageToVerifySignature #### Defined in -[eip2930Transaction.ts:307](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/eip2930Transaction.ts#L307) +[eip2930Transaction.ts:304](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/eip2930Transaction.ts#L304) ___ @@ -437,7 +437,7 @@ BaseTransaction.getSenderAddress #### Defined in -[baseTransaction.ts:293](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L293) +[baseTransaction.ts:301](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L301) ___ @@ -457,7 +457,7 @@ BaseTransaction.getSenderPublicKey #### Defined in -[eip2930Transaction.ts:314](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/eip2930Transaction.ts#L314) +[eip2930Transaction.ts:311](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/eip2930Transaction.ts#L311) ___ @@ -477,7 +477,7 @@ BaseTransaction.getUpfrontCost #### Defined in -[eip2930Transaction.ts:205](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/eip2930Transaction.ts#L205) +[eip2930Transaction.ts:202](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/eip2930Transaction.ts#L202) ___ @@ -500,7 +500,7 @@ BaseTransaction.hash #### Defined in -[eip2930Transaction.ts:288](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/eip2930Transaction.ts#L288) +[eip2930Transaction.ts:285](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/eip2930Transaction.ts#L285) ___ @@ -518,7 +518,7 @@ BaseTransaction.isSigned #### Defined in -[baseTransaction.ts:268](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L268) +[baseTransaction.ts:276](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L276) ___ @@ -548,7 +548,7 @@ BaseTransaction.raw #### Defined in -[eip2930Transaction.ts:222](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/eip2930Transaction.ts#L222) +[eip2930Transaction.ts:219](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/eip2930Transaction.ts#L219) ___ @@ -575,7 +575,7 @@ BaseTransaction.serialize #### Defined in -[eip2930Transaction.ts:248](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/eip2930Transaction.ts#L248) +[eip2930Transaction.ts:245](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/eip2930Transaction.ts#L245) ___ @@ -607,7 +607,7 @@ BaseTransaction.sign #### Defined in -[baseTransaction.ts:311](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L311) +[baseTransaction.ts:319](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L319) ___ @@ -646,7 +646,7 @@ BaseTransaction.supports #### Defined in -[baseTransaction.ts:146](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L146) +[baseTransaction.ts:154](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L154) ___ @@ -666,7 +666,7 @@ BaseTransaction.toCreationAddress #### Defined in -[baseTransaction.ts:236](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L236) +[baseTransaction.ts:244](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L244) ___ @@ -686,7 +686,7 @@ BaseTransaction.toJSON #### Defined in -[eip2930Transaction.ts:362](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/eip2930Transaction.ts#L362) +[eip2930Transaction.ts:359](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/eip2930Transaction.ts#L359) ___ @@ -707,7 +707,7 @@ BaseTransaction.validate #### Defined in -[baseTransaction.ts:154](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L154) +[baseTransaction.ts:162](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L162) ▸ **validate**(`stringError`): `boolean` @@ -727,7 +727,7 @@ BaseTransaction.validate #### Defined in -[baseTransaction.ts:155](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L155) +[baseTransaction.ts:163](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L163) ▸ **validate**(`stringError`): `string`[] @@ -747,7 +747,7 @@ BaseTransaction.validate #### Defined in -[baseTransaction.ts:156](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L156) +[baseTransaction.ts:164](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L164) ___ @@ -767,7 +767,7 @@ BaseTransaction.verifySignature #### Defined in -[baseTransaction.ts:280](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L280) +[baseTransaction.ts:288](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L288) ___ diff --git a/packages/tx/docs/classes/BlobEIP4844Transaction.md b/packages/tx/docs/classes/BlobEIP4844Transaction.md new file mode 100644 index 0000000000..a12c3d1151 --- /dev/null +++ b/packages/tx/docs/classes/BlobEIP4844Transaction.md @@ -0,0 +1,997 @@ +[@ethereumjs/tx](../README.md) / BlobEIP4844Transaction + +# Class: BlobEIP4844Transaction + +Typed transaction with a new gas fee market mechanism for transactions that include "blobs" of data + +- TransactionType: 5 +- EIP: [EIP-4844](https://eips.ethereum.org/EIPS/eip-4844) + +## Hierarchy + +- `BaseTransaction`<[`BlobEIP4844Transaction`](BlobEIP4844Transaction.md)\> + + ↳ **`BlobEIP4844Transaction`** + +## Table of contents + +### Constructors + +- [constructor](BlobEIP4844Transaction.md#constructor) + +### Properties + +- [AccessListJSON](BlobEIP4844Transaction.md#accesslistjson) +- [accessList](BlobEIP4844Transaction.md#accesslist) +- [aggregateKzgProof](BlobEIP4844Transaction.md#aggregatekzgproof) +- [blobs](BlobEIP4844Transaction.md#blobs) +- [chainId](BlobEIP4844Transaction.md#chainid) +- [common](BlobEIP4844Transaction.md#common) +- [data](BlobEIP4844Transaction.md#data) +- [gasLimit](BlobEIP4844Transaction.md#gaslimit) +- [kzgCommitments](BlobEIP4844Transaction.md#kzgcommitments) +- [maxFeePerDataGas](BlobEIP4844Transaction.md#maxfeeperdatagas) +- [maxFeePerGas](BlobEIP4844Transaction.md#maxfeepergas) +- [maxPriorityFeePerGas](BlobEIP4844Transaction.md#maxpriorityfeepergas) +- [nonce](BlobEIP4844Transaction.md#nonce) +- [r](BlobEIP4844Transaction.md#r) +- [s](BlobEIP4844Transaction.md#s) +- [to](BlobEIP4844Transaction.md#to) +- [v](BlobEIP4844Transaction.md#v) +- [value](BlobEIP4844Transaction.md#value) +- [versionedHashes](BlobEIP4844Transaction.md#versionedhashes) + +### Accessors + +- [type](BlobEIP4844Transaction.md#type) + +### Methods + +- [\_processSignature](BlobEIP4844Transaction.md#_processsignature) +- [errorStr](BlobEIP4844Transaction.md#errorstr) +- [getBaseFee](BlobEIP4844Transaction.md#getbasefee) +- [getDataFee](BlobEIP4844Transaction.md#getdatafee) +- [getMessageToSign](BlobEIP4844Transaction.md#getmessagetosign) +- [getMessageToVerifySignature](BlobEIP4844Transaction.md#getmessagetoverifysignature) +- [getSenderAddress](BlobEIP4844Transaction.md#getsenderaddress) +- [getSenderPublicKey](BlobEIP4844Transaction.md#getsenderpublickey) +- [getUpfrontCost](BlobEIP4844Transaction.md#getupfrontcost) +- [hash](BlobEIP4844Transaction.md#hash) +- [isSigned](BlobEIP4844Transaction.md#issigned) +- [numBlobs](BlobEIP4844Transaction.md#numblobs) +- [raw](BlobEIP4844Transaction.md#raw) +- [serialize](BlobEIP4844Transaction.md#serialize) +- [serializeNetworkWrapper](BlobEIP4844Transaction.md#serializenetworkwrapper) +- [sign](BlobEIP4844Transaction.md#sign) +- [supports](BlobEIP4844Transaction.md#supports) +- [toCreationAddress](BlobEIP4844Transaction.md#tocreationaddress) +- [toJSON](BlobEIP4844Transaction.md#tojson) +- [toValue](BlobEIP4844Transaction.md#tovalue) +- [unsignedHash](BlobEIP4844Transaction.md#unsignedhash) +- [validate](BlobEIP4844Transaction.md#validate) +- [verifySignature](BlobEIP4844Transaction.md#verifysignature) +- [fromSerializedBlobTxNetworkWrapper](BlobEIP4844Transaction.md#fromserializedblobtxnetworkwrapper) +- [fromSerializedTx](BlobEIP4844Transaction.md#fromserializedtx) +- [fromTxData](BlobEIP4844Transaction.md#fromtxdata) +- [minimalFromNetworkWrapper](BlobEIP4844Transaction.md#minimalfromnetworkwrapper) + +## Constructors + +### constructor + +• **new BlobEIP4844Transaction**(`txData`, `opts?`) + +This constructor takes the values, validates them, assigns them and freezes the object. + +It is not recommended to use this constructor directly. Instead use +the static constructors or factory methods to assist in creating a Transaction object from +varying data types. + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `txData` | [`BlobEIP4844TxData`](../interfaces/BlobEIP4844TxData.md) | +| `opts` | [`TxOptions`](../interfaces/TxOptions.md) | + +#### Overrides + +BaseTransaction<BlobEIP4844Transaction\>.constructor + +#### Defined in + +[eip4844Transaction.ts:91](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/eip4844Transaction.ts#L91) + +## Properties + +### AccessListJSON + +• `Readonly` **AccessListJSON**: [`AccessList`](../README.md#accesslist) + +#### Defined in + +[eip4844Transaction.ts:73](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/eip4844Transaction.ts#L73) + +___ + +### accessList + +• `Readonly` **accessList**: [`AccessListBuffer`](../README.md#accesslistbuffer) + +#### Defined in + +[eip4844Transaction.ts:72](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/eip4844Transaction.ts#L72) + +___ + +### aggregateKzgProof + +• `Optional` **aggregateKzgProof**: `Buffer` + +#### Defined in + +[eip4844Transaction.ts:82](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/eip4844Transaction.ts#L82) + +___ + +### blobs + +• `Optional` **blobs**: `Buffer`[] + +#### Defined in + +[eip4844Transaction.ts:80](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/eip4844Transaction.ts#L80) + +___ + +### chainId + +• `Readonly` **chainId**: `bigint` + +#### Defined in + +[eip4844Transaction.ts:71](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/eip4844Transaction.ts#L71) + +___ + +### common + +• `Readonly` **common**: `Common` + +#### Overrides + +BaseTransaction.common + +#### Defined in + +[eip4844Transaction.ts:78](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/eip4844Transaction.ts#L78) + +___ + +### data + +• `Readonly` **data**: `Buffer` + +#### Inherited from + +BaseTransaction.data + +#### Defined in + +[baseTransaction.ts:52](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L52) + +___ + +### gasLimit + +• `Readonly` **gasLimit**: `bigint` + +#### Inherited from + +BaseTransaction.gasLimit + +#### Defined in + +[baseTransaction.ts:49](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L49) + +___ + +### kzgCommitments + +• `Optional` **kzgCommitments**: `Buffer`[] + +#### Defined in + +[eip4844Transaction.ts:81](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/eip4844Transaction.ts#L81) + +___ + +### maxFeePerDataGas + +• `Readonly` **maxFeePerDataGas**: `bigint` + +#### Defined in + +[eip4844Transaction.ts:76](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/eip4844Transaction.ts#L76) + +___ + +### maxFeePerGas + +• `Readonly` **maxFeePerGas**: `bigint` + +#### Defined in + +[eip4844Transaction.ts:75](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/eip4844Transaction.ts#L75) + +___ + +### maxPriorityFeePerGas + +• `Readonly` **maxPriorityFeePerGas**: `bigint` + +#### Defined in + +[eip4844Transaction.ts:74](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/eip4844Transaction.ts#L74) + +___ + +### nonce + +• `Readonly` **nonce**: `bigint` + +#### Inherited from + +BaseTransaction.nonce + +#### Defined in + +[baseTransaction.ts:48](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L48) + +___ + +### r + +• `Optional` `Readonly` **r**: `bigint` + +#### Inherited from + +BaseTransaction.r + +#### Defined in + +[baseTransaction.ts:55](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L55) + +___ + +### s + +• `Optional` `Readonly` **s**: `bigint` + +#### Inherited from + +BaseTransaction.s + +#### Defined in + +[baseTransaction.ts:56](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L56) + +___ + +### to + +• `Optional` `Readonly` **to**: `Address` + +#### Inherited from + +BaseTransaction.to + +#### Defined in + +[baseTransaction.ts:50](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L50) + +___ + +### v + +• `Optional` `Readonly` **v**: `bigint` + +#### Inherited from + +BaseTransaction.v + +#### Defined in + +[baseTransaction.ts:54](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L54) + +___ + +### value + +• `Readonly` **value**: `bigint` + +#### Inherited from + +BaseTransaction.value + +#### Defined in + +[baseTransaction.ts:51](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L51) + +___ + +### versionedHashes + +• **versionedHashes**: `Buffer`[] + +#### Defined in + +[eip4844Transaction.ts:79](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/eip4844Transaction.ts#L79) + +## Accessors + +### type + +• `get` **type**(): `number` + +Returns the transaction type. + +Note: legacy txs will return tx type `0`. + +#### Returns + +`number` + +#### Inherited from + +BaseTransaction.type + +#### Defined in + +[baseTransaction.ts:134](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L134) + +## Methods + +### \_processSignature + +▸ **_processSignature**(`v`, `r`, `s`): [`BlobEIP4844Transaction`](BlobEIP4844Transaction.md) + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `v` | `bigint` | +| `r` | `Buffer` | +| `s` | `Buffer` | + +#### Returns + +[`BlobEIP4844Transaction`](BlobEIP4844Transaction.md) + +#### Overrides + +BaseTransaction.\_processSignature + +#### Defined in + +[eip4844Transaction.ts:446](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/eip4844Transaction.ts#L446) + +___ + +### errorStr + +▸ **errorStr**(): `string` + +Return a compact error string representation of the object + +#### Returns + +`string` + +#### Overrides + +BaseTransaction.errorStr + +#### Defined in + +[eip4844Transaction.ts:475](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/eip4844Transaction.ts#L475) + +___ + +### getBaseFee + +▸ **getBaseFee**(): `bigint` + +The minimum amount of gas the tx must have (DataFee + TxFee + Creation Fee) + +#### Returns + +`bigint` + +#### Inherited from + +BaseTransaction.getBaseFee + +#### Defined in + +[baseTransaction.ts:204](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L204) + +___ + +### getDataFee + +▸ **getDataFee**(): `bigint` + +The amount of gas paid for the data in this tx + +#### Returns + +`bigint` + +#### Inherited from + +BaseTransaction.getDataFee + +#### Defined in + +[baseTransaction.ts:218](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L218) + +___ + +### getMessageToSign + +▸ **getMessageToSign**(`hashMessage`): `Buffer` \| `Buffer`[] + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `hashMessage` | ``false`` | + +#### Returns + +`Buffer` \| `Buffer`[] + +#### Overrides + +BaseTransaction.getMessageToSign + +#### Defined in + +[eip4844Transaction.ts:377](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/eip4844Transaction.ts#L377) + +▸ **getMessageToSign**(`hashMessage?`): `Buffer` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `hashMessage?` | ``true`` | + +#### Returns + +`Buffer` + +#### Overrides + +BaseTransaction.getMessageToSign + +#### Defined in + +[eip4844Transaction.ts:378](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/eip4844Transaction.ts#L378) + +___ + +### getMessageToVerifySignature + +▸ **getMessageToVerifySignature**(): `Buffer` + +#### Returns + +`Buffer` + +#### Overrides + +BaseTransaction.getMessageToVerifySignature + +#### Defined in + +[eip4844Transaction.ts:395](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/eip4844Transaction.ts#L395) + +___ + +### getSenderAddress + +▸ **getSenderAddress**(): `Address` + +Returns the sender's address + +#### Returns + +`Address` + +#### Inherited from + +BaseTransaction.getSenderAddress + +#### Defined in + +[baseTransaction.ts:301](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L301) + +___ + +### getSenderPublicKey + +▸ **getSenderPublicKey**(): `Buffer` + +Returns the public key of the sender + +#### Returns + +`Buffer` + +#### Overrides + +BaseTransaction.getSenderPublicKey + +#### Defined in + +[eip4844Transaction.ts:402](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/eip4844Transaction.ts#L402) + +___ + +### getUpfrontCost + +▸ **getUpfrontCost**(`baseFee?`): `bigint` + +The up front amount that an account must have for this transaction to be valid + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `baseFee` | `bigint` | The base fee of the block (will be set to 0 if not provided) | + +#### Returns + +`bigint` + +#### Overrides + +BaseTransaction.getUpfrontCost + +#### Defined in + +[eip4844Transaction.ts:294](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/eip4844Transaction.ts#L294) + +___ + +### hash + +▸ **hash**(): `Buffer` + +#### Returns + +`Buffer` + +#### Overrides + +BaseTransaction.hash + +#### Defined in + +[eip4844Transaction.ts:391](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/eip4844Transaction.ts#L391) + +___ + +### isSigned + +▸ **isSigned**(): `boolean` + +#### Returns + +`boolean` + +#### Inherited from + +BaseTransaction.isSigned + +#### Defined in + +[baseTransaction.ts:276](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L276) + +___ + +### numBlobs + +▸ **numBlobs**(): `number` + +#### Returns + +`number` + +the number of blobs included with this transaction + +#### Defined in + +[eip4844Transaction.ts:494](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/eip4844Transaction.ts#L494) + +___ + +### raw + +▸ **raw**(): [`TxValuesArray`](../README.md#txvaluesarray) + +This method is not implemented for blob transactions as the `raw` method is used exclusively with +rlp encoding and these transactions use SSZ for serialization. + +#### Returns + +[`TxValuesArray`](../README.md#txvaluesarray) + +#### Overrides + +BaseTransaction.raw + +#### Defined in + +[eip4844Transaction.ts:306](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/eip4844Transaction.ts#L306) + +___ + +### serialize + +▸ **serialize**(): `Buffer` + +Serialize a blob transaction to the execution payload variant + +#### Returns + +`Buffer` + +the minimum (execution payload) serialization of a signed transaction + +#### Overrides + +BaseTransaction.serialize + +#### Defined in + +[eip4844Transaction.ts:344](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/eip4844Transaction.ts#L344) + +___ + +### serializeNetworkWrapper + +▸ **serializeNetworkWrapper**(): `Buffer` + +#### Returns + +`Buffer` + +the serialized form of a blob transaction in the network wrapper format (used for gossipping mempool transactions over devp2p) + +#### Defined in + +[eip4844Transaction.ts:352](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/eip4844Transaction.ts#L352) + +___ + +### sign + +▸ **sign**(`privateKey`): [`BlobEIP4844Transaction`](BlobEIP4844Transaction.md) + +Signs a transaction. + +Note that the signed tx is returned as a new object, +use as follows: +```javascript +const signedTx = tx.sign(privateKey) +``` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `privateKey` | `Buffer` | + +#### Returns + +[`BlobEIP4844Transaction`](BlobEIP4844Transaction.md) + +#### Inherited from + +BaseTransaction.sign + +#### Defined in + +[baseTransaction.ts:319](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L319) + +___ + +### supports + +▸ **supports**(`capability`): `boolean` + +Checks if a tx type defining capability is active +on a tx, for example the EIP-1559 fee market mechanism +or the EIP-2930 access list feature. + +Note that this is different from the tx type itself, +so EIP-2930 access lists can very well be active +on an EIP-1559 tx for example. + +This method can be useful for feature checks if the +tx type is unknown (e.g. when instantiated with +the tx factory). + +See `Capabilites` in the `types` module for a reference +on all supported capabilities. + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `capability` | [`Capability`](../enums/Capability.md) | + +#### Returns + +`boolean` + +#### Inherited from + +BaseTransaction.supports + +#### Defined in + +[baseTransaction.ts:154](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L154) + +___ + +### toCreationAddress + +▸ **toCreationAddress**(): `boolean` + +If the tx's `to` is to the creation address + +#### Returns + +`boolean` + +#### Inherited from + +BaseTransaction.toCreationAddress + +#### Defined in + +[baseTransaction.ts:244](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L244) + +___ + +### toJSON + +▸ **toJSON**(): [`JsonTx`](../interfaces/JsonTx.md) + +#### Returns + +[`JsonTx`](../interfaces/JsonTx.md) + +#### Overrides + +BaseTransaction.toJSON + +#### Defined in + +[eip4844Transaction.ts:426](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/eip4844Transaction.ts#L426) + +___ + +### toValue + +▸ **toValue**(): `ValueOfFields`<{ `message`: `ContainerType`<{ `accessList`: `ListCompositeType`<`ContainerType`<{ `address`: `ByteVectorType` = AddressType; `storageKeys`: `ListCompositeType`<`ByteVectorType`\> }\>\> ; `blobVersionedHashes`: `ListCompositeType`<`ByteVectorType`\> ; `chainId`: `UintBigintType` = Uint256; `data`: `ByteListType` ; `gas`: `UintBigintType` = Uint64; `maxFeePerDataGas`: `UintBigintType` = Uint256; `maxFeePerGas`: `UintBigintType` = Uint256; `maxPriorityFeePerGas`: `UintBigintType` = Uint256; `nonce`: `UintBigintType` = Uint64; `to`: `UnionType`<(`ByteVectorType` \| `NoneType`)[]\> ; `value`: `UintBigintType` = Uint256 }\> = BlobTransactionType; `signature`: `ContainerType`<{ `r`: `UintBigintType` = Uint256; `s`: `UintBigintType` = Uint256; `yParity`: `BooleanType` }\> = ECDSASignatureType }\> + +#### Returns + +`ValueOfFields`<{ `message`: `ContainerType`<{ `accessList`: `ListCompositeType`<`ContainerType`<{ `address`: `ByteVectorType` = AddressType; `storageKeys`: `ListCompositeType`<`ByteVectorType`\> }\>\> ; `blobVersionedHashes`: `ListCompositeType`<`ByteVectorType`\> ; `chainId`: `UintBigintType` = Uint256; `data`: `ByteListType` ; `gas`: `UintBigintType` = Uint64; `maxFeePerDataGas`: `UintBigintType` = Uint256; `maxFeePerGas`: `UintBigintType` = Uint256; `maxPriorityFeePerGas`: `UintBigintType` = Uint256; `nonce`: `UintBigintType` = Uint64; `to`: `UnionType`<(`ByteVectorType` \| `NoneType`)[]\> ; `value`: `UintBigintType` = Uint256 }\> = BlobTransactionType; `signature`: `ContainerType`<{ `r`: `UintBigintType` = Uint256; `s`: `UintBigintType` = Uint256; `yParity`: `BooleanType` }\> = ECDSASignatureType }\> + +#### Defined in + +[eip4844Transaction.ts:310](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/eip4844Transaction.ts#L310) + +___ + +### unsignedHash + +▸ **unsignedHash**(): `Buffer` + +Returns the hash of a blob transaction + +#### Returns + +`Buffer` + +#### Defined in + +[eip4844Transaction.ts:386](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/eip4844Transaction.ts#L386) + +___ + +### validate + +▸ **validate**(): `boolean` + +Checks if the transaction has the minimum amount of gas required +(DataFee + TxFee + Creation Fee). + +#### Returns + +`boolean` + +#### Inherited from + +BaseTransaction.validate + +#### Defined in + +[baseTransaction.ts:162](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L162) + +▸ **validate**(`stringError`): `boolean` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `stringError` | ``false`` | + +#### Returns + +`boolean` + +#### Inherited from + +BaseTransaction.validate + +#### Defined in + +[baseTransaction.ts:163](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L163) + +▸ **validate**(`stringError`): `string`[] + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `stringError` | ``true`` | + +#### Returns + +`string`[] + +#### Inherited from + +BaseTransaction.validate + +#### Defined in + +[baseTransaction.ts:164](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L164) + +___ + +### verifySignature + +▸ **verifySignature**(): `boolean` + +Determines if the signature is valid + +#### Returns + +`boolean` + +#### Inherited from + +BaseTransaction.verifySignature + +#### Defined in + +[baseTransaction.ts:288](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L288) + +___ + +### fromSerializedBlobTxNetworkWrapper + +▸ `Static` **fromSerializedBlobTxNetworkWrapper**(`serialized`, `opts?`): [`BlobEIP4844Transaction`](BlobEIP4844Transaction.md) + +Creates a transaction from the network encoding of a blob transaction (with blobs/commitments/proof) + +**`Throws`** + +if no KZG library is loaded -- using the `initKzg` helper method -- or if `opts.common` not provided + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `serialized` | `Buffer` | a buffer representing a serialized BlobTransactionNetworkWrapper | +| `opts?` | [`TxOptions`](../interfaces/TxOptions.md) | any TxOptions defined | + +#### Returns + +[`BlobEIP4844Transaction`](BlobEIP4844Transaction.md) + +a BlobEIP4844Transaction + +#### Defined in + +[eip4844Transaction.ts:201](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/eip4844Transaction.ts#L201) + +___ + +### fromSerializedTx + +▸ `Static` **fromSerializedTx**(`serialized`, `opts?`): [`BlobEIP4844Transaction`](BlobEIP4844Transaction.md) + +Creates a transaction from the "minimal" encoding of a blob transaction (without blobs/commitments/kzg proof) + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `serialized` | `Buffer` | a buffer representing a serialized signed blob transaction | +| `opts?` | [`TxOptions`](../interfaces/TxOptions.md) | any TxOptions defined | + +#### Returns + +[`BlobEIP4844Transaction`](BlobEIP4844Transaction.md) + +a BlobEIP4844Transaction + +#### Defined in + +[eip4844Transaction.ts:262](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/eip4844Transaction.ts#L262) + +___ + +### fromTxData + +▸ `Static` **fromTxData**(`txData`, `opts?`): [`BlobEIP4844Transaction`](BlobEIP4844Transaction.md) + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `txData` | [`BlobEIP4844TxData`](../interfaces/BlobEIP4844TxData.md) | +| `opts?` | [`TxOptions`](../interfaces/TxOptions.md) | + +#### Returns + +[`BlobEIP4844Transaction`](BlobEIP4844Transaction.md) + +#### Defined in + +[eip4844Transaction.ts:172](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/eip4844Transaction.ts#L172) + +___ + +### minimalFromNetworkWrapper + +▸ `Static` **minimalFromNetworkWrapper**(`txData`, `opts?`): [`BlobEIP4844Transaction`](BlobEIP4844Transaction.md) + +Creates the minimal representation of a blob transaction from the network wrapper version. +The minimal representation is used when adding transactions to an execution payload/block + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `txData` | [`BlobEIP4844Transaction`](BlobEIP4844Transaction.md) | a [BlobEIP4844Transaction](BlobEIP4844Transaction.md) containing optional blobs/kzg commitments | +| `opts?` | [`TxOptions`](../interfaces/TxOptions.md) | dictionary of [TxOptions](../interfaces/TxOptions.md) | + +#### Returns + +[`BlobEIP4844Transaction`](BlobEIP4844Transaction.md) + +the "minimal" representation of a BlobEIP4844Transaction (i.e. transaction object minus blobs and kzg commitments) + +#### Defined in + +[eip4844Transaction.ts:183](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/eip4844Transaction.ts#L183) diff --git a/packages/tx/docs/classes/FeeMarketEIP1559Transaction.md b/packages/tx/docs/classes/FeeMarketEIP1559Transaction.md index 8223c607a7..afb408adfa 100644 --- a/packages/tx/docs/classes/FeeMarketEIP1559Transaction.md +++ b/packages/tx/docs/classes/FeeMarketEIP1559Transaction.md @@ -148,7 +148,7 @@ BaseTransaction.data #### Defined in -[baseTransaction.ts:51](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L51) +[baseTransaction.ts:52](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L52) ___ @@ -162,7 +162,7 @@ BaseTransaction.gasLimit #### Defined in -[baseTransaction.ts:48](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L48) +[baseTransaction.ts:49](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L49) ___ @@ -196,7 +196,7 @@ BaseTransaction.nonce #### Defined in -[baseTransaction.ts:47](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L47) +[baseTransaction.ts:48](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L48) ___ @@ -210,7 +210,7 @@ BaseTransaction.r #### Defined in -[baseTransaction.ts:54](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L54) +[baseTransaction.ts:55](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L55) ___ @@ -224,7 +224,7 @@ BaseTransaction.s #### Defined in -[baseTransaction.ts:55](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L55) +[baseTransaction.ts:56](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L56) ___ @@ -238,7 +238,7 @@ BaseTransaction.to #### Defined in -[baseTransaction.ts:49](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L49) +[baseTransaction.ts:50](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L50) ___ @@ -252,7 +252,7 @@ BaseTransaction.v #### Defined in -[baseTransaction.ts:53](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L53) +[baseTransaction.ts:54](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L54) ___ @@ -266,7 +266,7 @@ BaseTransaction.value #### Defined in -[baseTransaction.ts:50](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L50) +[baseTransaction.ts:51](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L51) ## Accessors @@ -288,7 +288,7 @@ BaseTransaction.type #### Defined in -[baseTransaction.ts:126](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L126) +[baseTransaction.ts:134](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L134) ## Methods @@ -314,7 +314,7 @@ BaseTransaction.\_processSignature #### Defined in -[eip1559Transaction.ts:368](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/eip1559Transaction.ts#L368) +[eip1559Transaction.ts:364](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/eip1559Transaction.ts#L364) ___ @@ -334,7 +334,7 @@ BaseTransaction.errorStr #### Defined in -[eip1559Transaction.ts:415](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/eip1559Transaction.ts#L415) +[eip1559Transaction.ts:411](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/eip1559Transaction.ts#L411) ___ @@ -354,7 +354,7 @@ BaseTransaction.getBaseFee #### Defined in -[baseTransaction.ts:196](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L196) +[baseTransaction.ts:204](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L204) ___ @@ -374,7 +374,7 @@ BaseTransaction.getDataFee #### Defined in -[eip1559Transaction.ts:208](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/eip1559Transaction.ts#L208) +[eip1559Transaction.ts:204](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/eip1559Transaction.ts#L204) ___ @@ -408,7 +408,7 @@ BaseTransaction.getMessageToSign #### Defined in -[eip1559Transaction.ts:299](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/eip1559Transaction.ts#L299) +[eip1559Transaction.ts:295](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/eip1559Transaction.ts#L295) ___ @@ -428,7 +428,7 @@ BaseTransaction.getMessageToVerifySignature #### Defined in -[eip1559Transaction.ts:337](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/eip1559Transaction.ts#L337) +[eip1559Transaction.ts:333](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/eip1559Transaction.ts#L333) ___ @@ -448,7 +448,7 @@ BaseTransaction.getSenderAddress #### Defined in -[baseTransaction.ts:293](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L293) +[baseTransaction.ts:301](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L301) ___ @@ -468,7 +468,7 @@ BaseTransaction.getSenderPublicKey #### Defined in -[eip1559Transaction.ts:344](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/eip1559Transaction.ts#L344) +[eip1559Transaction.ts:340](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/eip1559Transaction.ts#L340) ___ @@ -494,7 +494,7 @@ BaseTransaction.getUpfrontCost #### Defined in -[eip1559Transaction.ts:230](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/eip1559Transaction.ts#L230) +[eip1559Transaction.ts:226](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/eip1559Transaction.ts#L226) ___ @@ -517,7 +517,7 @@ BaseTransaction.hash #### Defined in -[eip1559Transaction.ts:318](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/eip1559Transaction.ts#L318) +[eip1559Transaction.ts:314](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/eip1559Transaction.ts#L314) ___ @@ -535,7 +535,7 @@ BaseTransaction.isSigned #### Defined in -[baseTransaction.ts:268](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L268) +[baseTransaction.ts:276](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L276) ___ @@ -565,7 +565,7 @@ BaseTransaction.raw #### Defined in -[eip1559Transaction.ts:251](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/eip1559Transaction.ts#L251) +[eip1559Transaction.ts:247](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/eip1559Transaction.ts#L247) ___ @@ -592,7 +592,7 @@ BaseTransaction.serialize #### Defined in -[eip1559Transaction.ts:278](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/eip1559Transaction.ts#L278) +[eip1559Transaction.ts:274](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/eip1559Transaction.ts#L274) ___ @@ -624,7 +624,7 @@ BaseTransaction.sign #### Defined in -[baseTransaction.ts:311](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L311) +[baseTransaction.ts:319](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L319) ___ @@ -663,7 +663,7 @@ BaseTransaction.supports #### Defined in -[baseTransaction.ts:146](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L146) +[baseTransaction.ts:154](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L154) ___ @@ -683,7 +683,7 @@ BaseTransaction.toCreationAddress #### Defined in -[baseTransaction.ts:236](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L236) +[baseTransaction.ts:244](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L244) ___ @@ -703,7 +703,7 @@ BaseTransaction.toJSON #### Defined in -[eip1559Transaction.ts:393](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/eip1559Transaction.ts#L393) +[eip1559Transaction.ts:389](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/eip1559Transaction.ts#L389) ___ @@ -724,7 +724,7 @@ BaseTransaction.validate #### Defined in -[baseTransaction.ts:154](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L154) +[baseTransaction.ts:162](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L162) ▸ **validate**(`stringError`): `boolean` @@ -744,7 +744,7 @@ BaseTransaction.validate #### Defined in -[baseTransaction.ts:155](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L155) +[baseTransaction.ts:163](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L163) ▸ **validate**(`stringError`): `string`[] @@ -764,7 +764,7 @@ BaseTransaction.validate #### Defined in -[baseTransaction.ts:156](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L156) +[baseTransaction.ts:164](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L164) ___ @@ -784,7 +784,7 @@ BaseTransaction.verifySignature #### Defined in -[baseTransaction.ts:280](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L280) +[baseTransaction.ts:288](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L288) ___ diff --git a/packages/tx/docs/classes/Transaction.md b/packages/tx/docs/classes/Transaction.md index 4ff42c88a0..8fd4753c9c 100644 --- a/packages/tx/docs/classes/Transaction.md +++ b/packages/tx/docs/classes/Transaction.md @@ -82,7 +82,7 @@ BaseTransaction<Transaction\>.constructor #### Defined in -[legacyTransaction.ts:107](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/legacyTransaction.ts#L107) +[legacyTransaction.ts:106](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/legacyTransaction.ts#L106) ## Properties @@ -96,7 +96,7 @@ BaseTransaction.common #### Defined in -[legacyTransaction.ts:37](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/legacyTransaction.ts#L37) +[legacyTransaction.ts:36](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/legacyTransaction.ts#L36) ___ @@ -110,7 +110,7 @@ BaseTransaction.data #### Defined in -[baseTransaction.ts:51](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L51) +[baseTransaction.ts:52](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L52) ___ @@ -124,7 +124,7 @@ BaseTransaction.gasLimit #### Defined in -[baseTransaction.ts:48](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L48) +[baseTransaction.ts:49](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L49) ___ @@ -134,7 +134,7 @@ ___ #### Defined in -[legacyTransaction.ts:35](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/legacyTransaction.ts#L35) +[legacyTransaction.ts:34](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/legacyTransaction.ts#L34) ___ @@ -148,7 +148,7 @@ BaseTransaction.nonce #### Defined in -[baseTransaction.ts:47](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L47) +[baseTransaction.ts:48](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L48) ___ @@ -162,7 +162,7 @@ BaseTransaction.r #### Defined in -[baseTransaction.ts:54](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L54) +[baseTransaction.ts:55](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L55) ___ @@ -176,7 +176,7 @@ BaseTransaction.s #### Defined in -[baseTransaction.ts:55](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L55) +[baseTransaction.ts:56](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L56) ___ @@ -190,7 +190,7 @@ BaseTransaction.to #### Defined in -[baseTransaction.ts:49](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L49) +[baseTransaction.ts:50](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L50) ___ @@ -204,7 +204,7 @@ BaseTransaction.v #### Defined in -[baseTransaction.ts:53](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L53) +[baseTransaction.ts:54](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L54) ___ @@ -218,7 +218,7 @@ BaseTransaction.value #### Defined in -[baseTransaction.ts:50](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L50) +[baseTransaction.ts:51](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L51) ## Accessors @@ -240,7 +240,7 @@ BaseTransaction.type #### Defined in -[baseTransaction.ts:126](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L126) +[baseTransaction.ts:134](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L134) ## Methods @@ -260,7 +260,7 @@ BaseTransaction.errorStr #### Defined in -[legacyTransaction.ts:408](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/legacyTransaction.ts#L408) +[legacyTransaction.ts:403](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/legacyTransaction.ts#L403) ___ @@ -280,7 +280,7 @@ BaseTransaction.getBaseFee #### Defined in -[baseTransaction.ts:196](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L196) +[baseTransaction.ts:204](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L204) ___ @@ -300,7 +300,7 @@ BaseTransaction.getDataFee #### Defined in -[legacyTransaction.ts:236](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/legacyTransaction.ts#L236) +[legacyTransaction.ts:231](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/legacyTransaction.ts#L231) ___ @@ -337,7 +337,7 @@ BaseTransaction.getMessageToSign #### Defined in -[legacyTransaction.ts:222](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/legacyTransaction.ts#L222) +[legacyTransaction.ts:217](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/legacyTransaction.ts#L217) ▸ **getMessageToSign**(`hashMessage?`): `Buffer` @@ -357,7 +357,7 @@ BaseTransaction.getMessageToSign #### Defined in -[legacyTransaction.ts:223](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/legacyTransaction.ts#L223) +[legacyTransaction.ts:218](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/legacyTransaction.ts#L218) ___ @@ -377,7 +377,7 @@ BaseTransaction.getMessageToVerifySignature #### Defined in -[legacyTransaction.ts:283](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/legacyTransaction.ts#L283) +[legacyTransaction.ts:278](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/legacyTransaction.ts#L278) ___ @@ -397,7 +397,7 @@ BaseTransaction.getSenderAddress #### Defined in -[baseTransaction.ts:293](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L293) +[baseTransaction.ts:301](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L301) ___ @@ -417,7 +417,7 @@ BaseTransaction.getSenderPublicKey #### Defined in -[legacyTransaction.ts:295](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/legacyTransaction.ts#L295) +[legacyTransaction.ts:290](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/legacyTransaction.ts#L290) ___ @@ -437,7 +437,7 @@ BaseTransaction.getUpfrontCost #### Defined in -[legacyTransaction.ts:254](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/legacyTransaction.ts#L254) +[legacyTransaction.ts:249](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/legacyTransaction.ts#L249) ___ @@ -460,7 +460,7 @@ BaseTransaction.hash #### Defined in -[legacyTransaction.ts:264](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/legacyTransaction.ts#L264) +[legacyTransaction.ts:259](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/legacyTransaction.ts#L259) ___ @@ -478,7 +478,7 @@ BaseTransaction.isSigned #### Defined in -[baseTransaction.ts:268](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L268) +[baseTransaction.ts:276](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L276) ___ @@ -508,7 +508,7 @@ BaseTransaction.raw #### Defined in -[legacyTransaction.ts:160](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/legacyTransaction.ts#L160) +[legacyTransaction.ts:155](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/legacyTransaction.ts#L155) ___ @@ -534,7 +534,7 @@ BaseTransaction.serialize #### Defined in -[legacyTransaction.ts:183](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/legacyTransaction.ts#L183) +[legacyTransaction.ts:178](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/legacyTransaction.ts#L178) ___ @@ -566,7 +566,7 @@ BaseTransaction.sign #### Defined in -[baseTransaction.ts:311](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L311) +[baseTransaction.ts:319](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L319) ___ @@ -605,7 +605,7 @@ BaseTransaction.supports #### Defined in -[baseTransaction.ts:146](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L146) +[baseTransaction.ts:154](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L154) ___ @@ -625,7 +625,7 @@ BaseTransaction.toCreationAddress #### Defined in -[baseTransaction.ts:236](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L236) +[baseTransaction.ts:244](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L244) ___ @@ -645,7 +645,7 @@ BaseTransaction.toJSON #### Defined in -[legacyTransaction.ts:345](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/legacyTransaction.ts#L345) +[legacyTransaction.ts:340](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/legacyTransaction.ts#L340) ___ @@ -666,7 +666,7 @@ BaseTransaction.validate #### Defined in -[baseTransaction.ts:154](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L154) +[baseTransaction.ts:162](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L162) ▸ **validate**(`stringError`): `boolean` @@ -686,7 +686,7 @@ BaseTransaction.validate #### Defined in -[baseTransaction.ts:155](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L155) +[baseTransaction.ts:163](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L163) ▸ **validate**(`stringError`): `string`[] @@ -706,7 +706,7 @@ BaseTransaction.validate #### Defined in -[baseTransaction.ts:156](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L156) +[baseTransaction.ts:164](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L164) ___ @@ -726,7 +726,7 @@ BaseTransaction.verifySignature #### Defined in -[baseTransaction.ts:280](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L280) +[baseTransaction.ts:288](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/baseTransaction.ts#L288) ___ @@ -751,7 +751,7 @@ Format: `rlp([nonce, gasPrice, gasLimit, to, value, data, v, r, s])` #### Defined in -[legacyTransaction.ts:56](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/legacyTransaction.ts#L56) +[legacyTransaction.ts:55](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/legacyTransaction.ts#L55) ___ @@ -779,7 +779,7 @@ Notes: #### Defined in -[legacyTransaction.ts:47](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/legacyTransaction.ts#L47) +[legacyTransaction.ts:46](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/legacyTransaction.ts#L46) ___ @@ -804,4 +804,4 @@ Format: `[nonce, gasPrice, gasLimit, to, value, data, v, r, s]` #### Defined in -[legacyTransaction.ts:71](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/legacyTransaction.ts#L71) +[legacyTransaction.ts:70](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/legacyTransaction.ts#L70) diff --git a/packages/tx/docs/classes/TransactionFactory.md b/packages/tx/docs/classes/TransactionFactory.md index 525f96b56c..3246cc81fd 100644 --- a/packages/tx/docs/classes/TransactionFactory.md +++ b/packages/tx/docs/classes/TransactionFactory.md @@ -8,6 +8,7 @@ - [fromBlockBodyData](TransactionFactory.md#fromblockbodydata) - [fromEthersProvider](TransactionFactory.md#fromethersprovider) +- [fromRPCTx](TransactionFactory.md#fromrpctx) - [fromSerializedData](TransactionFactory.md#fromserializeddata) - [fromTxData](TransactionFactory.md#fromtxdata) @@ -35,7 +36,7 @@ This method returns the right transaction. #### Defined in -[transactionFactory.ts:88](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/transactionFactory.ts#L88) +[transactionFactory.ts:84](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/transactionFactory.ts#L84) ___ @@ -49,7 +50,7 @@ Method to retrieve a transaction from the provider | Name | Type | Description | | :------ | :------ | :------ | -| `provider` | `string` \| `JsonRpcProvider` | An Ethers JsonRPCProvider | +| `provider` | `any` | An Ethers JsonRPCProvider | | `txHash` | `string` | Transaction hash | | `txOptions?` | [`TxOptions`](../interfaces/TxOptions.md) | The transaction options | @@ -61,7 +62,31 @@ the transaction specified by `txHash` #### Defined in -[transactionFactory.ts:106](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/transactionFactory.ts#L106) +[transactionFactory.ts:102](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/transactionFactory.ts#L102) + +___ + +### fromRPCTx + +▸ `Static` **fromRPCTx**(`txData`, `txOptions?`): `Promise`<[`TypedTransaction`](../README.md#typedtransaction)\> + +Method to decode data retrieved from RPC, such as `eth_getTransactionByHash` +Note that this normalizes some of the parameters + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `txData` | [`BlobEIP4844TxData`](../interfaces/BlobEIP4844TxData.md) \| [`FeeMarketEIP1559TxData`](../interfaces/FeeMarketEIP1559TxData.md) \| [`AccessListEIP2930TxData`](../interfaces/AccessListEIP2930TxData.md) \| [`TxData`](../README.md#txdata) | The RPC-encoded data | +| `txOptions` | [`TxOptions`](../interfaces/TxOptions.md) | The transaction options | + +#### Returns + +`Promise`<[`TypedTransaction`](../README.md#typedtransaction)\> + +#### Defined in + +[transactionFactory.ts:125](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/transactionFactory.ts#L125) ___ @@ -84,7 +109,7 @@ This method tries to decode serialized data. #### Defined in -[transactionFactory.ts:54](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/transactionFactory.ts#L54) +[transactionFactory.ts:57](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/transactionFactory.ts#L57) ___ @@ -98,7 +123,7 @@ Create a transaction from a `txData` object | Name | Type | Description | | :------ | :------ | :------ | -| `txData` | [`FeeMarketEIP1559TxData`](../interfaces/FeeMarketEIP1559TxData.md) \| [`AccessListEIP2930TxData`](../interfaces/AccessListEIP2930TxData.md) \| [`TxData`](../README.md#txdata) | The transaction data. The `type` field will determine which transaction type is returned (if undefined, creates a legacy transaction) | +| `txData` | [`BlobEIP4844TxData`](../interfaces/BlobEIP4844TxData.md) \| [`FeeMarketEIP1559TxData`](../interfaces/FeeMarketEIP1559TxData.md) \| [`AccessListEIP2930TxData`](../interfaces/AccessListEIP2930TxData.md) \| [`TxData`](../README.md#txdata) | The transaction data. The `type` field will determine which transaction type is returned (if undefined, creates a legacy transaction) | | `txOptions` | [`TxOptions`](../interfaces/TxOptions.md) | Options to pass on to the constructor of the transaction | #### Returns @@ -107,4 +132,4 @@ Create a transaction from a `txData` object #### Defined in -[transactionFactory.ts:27](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/transactionFactory.ts#L27) +[transactionFactory.ts:28](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/transactionFactory.ts#L28) diff --git a/packages/tx/docs/enums/Capability.md b/packages/tx/docs/enums/Capability.md index 02ec3c8a5c..41c4ef61e1 100644 --- a/packages/tx/docs/enums/Capability.md +++ b/packages/tx/docs/enums/Capability.md @@ -25,7 +25,7 @@ See: [1559](https://eips.ethereum.org/EIPS/eip-1559) Fee Market EIP #### Defined in -[types.ts:22](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L22) +[types.ts:51](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L51) ___ @@ -38,7 +38,7 @@ See: [155](https://eips.ethereum.org/EIPS/eip-155) Replay Attack Protection EIP #### Defined in -[types.ts:16](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L16) +[types.ts:45](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L45) ___ @@ -51,7 +51,7 @@ See: [2718](https://eips.ethereum.org/EIPS/eip-2718) Transaction Type EIP #### Defined in -[types.ts:28](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L28) +[types.ts:57](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L57) ___ @@ -64,4 +64,4 @@ See: [2930](https://eips.ethereum.org/EIPS/eip-2930) Access Lists EIP #### Defined in -[types.ts:34](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L34) +[types.ts:63](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L63) diff --git a/packages/tx/docs/interfaces/AccessListEIP2930TxData.md b/packages/tx/docs/interfaces/AccessListEIP2930TxData.md index cd0980a3e4..4766b583ef 100644 --- a/packages/tx/docs/interfaces/AccessListEIP2930TxData.md +++ b/packages/tx/docs/interfaces/AccessListEIP2930TxData.md @@ -33,13 +33,13 @@ ### accessList -• `Optional` **accessList**: [`AccessListBuffer`](../README.md#accesslistbuffer) \| [`AccessList`](../README.md#accesslist) +• `Optional` **accessList**: ``null`` \| [`AccessListBuffer`](../README.md#accesslistbuffer) \| [`AccessList`](../README.md#accesslist) The access list which contains the addresses/storage slots which the transaction wishes to access #### Defined in -[types.ts:178](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L178) +[types.ts:214](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L214) ___ @@ -51,7 +51,7 @@ The transaction's chain ID #### Defined in -[types.ts:173](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L173) +[types.ts:209](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L209) ___ @@ -67,7 +67,7 @@ TxData.data #### Defined in -[types.ts:142](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L142) +[types.ts:178](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L178) ___ @@ -83,13 +83,13 @@ TxData.gasLimit #### Defined in -[types.ts:127](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L127) +[types.ts:163](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L163) ___ ### gasPrice -• `Optional` **gasPrice**: `BigIntLike` +• `Optional` **gasPrice**: ``null`` \| `BigIntLike` The transaction's gas price. @@ -99,7 +99,7 @@ TxData.gasPrice #### Defined in -[types.ts:122](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L122) +[types.ts:158](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L158) ___ @@ -115,7 +115,7 @@ TxData.nonce #### Defined in -[types.ts:117](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L117) +[types.ts:153](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L153) ___ @@ -131,7 +131,7 @@ TxData.r #### Defined in -[types.ts:152](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L152) +[types.ts:188](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L188) ___ @@ -147,7 +147,7 @@ TxData.s #### Defined in -[types.ts:157](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L157) +[types.ts:193](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L193) ___ @@ -163,7 +163,7 @@ TxData.to #### Defined in -[types.ts:132](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L132) +[types.ts:168](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L168) ___ @@ -179,7 +179,7 @@ TxData.type #### Defined in -[types.ts:163](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L163) +[types.ts:199](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L199) ___ @@ -195,7 +195,7 @@ TxData.v #### Defined in -[types.ts:147](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L147) +[types.ts:183](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L183) ___ @@ -211,4 +211,4 @@ TxData.value #### Defined in -[types.ts:137](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L137) +[types.ts:173](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L173) diff --git a/packages/tx/docs/interfaces/BlobEIP4844TxData.md b/packages/tx/docs/interfaces/BlobEIP4844TxData.md new file mode 100644 index 0000000000..3c93e7007f --- /dev/null +++ b/packages/tx/docs/interfaces/BlobEIP4844TxData.md @@ -0,0 +1,320 @@ +[@ethereumjs/tx](../README.md) / BlobEIP4844TxData + +# Interface: BlobEIP4844TxData + +[BlobEIP4844Transaction](../classes/BlobEIP4844Transaction.md) data. + +## Hierarchy + +- [`FeeMarketEIP1559TxData`](FeeMarketEIP1559TxData.md) + + ↳ **`BlobEIP4844TxData`** + +## Table of contents + +### Properties + +- [accessList](BlobEIP4844TxData.md#accesslist) +- [blobs](BlobEIP4844TxData.md#blobs) +- [chainId](BlobEIP4844TxData.md#chainid) +- [data](BlobEIP4844TxData.md#data) +- [gasLimit](BlobEIP4844TxData.md#gaslimit) +- [gasPrice](BlobEIP4844TxData.md#gasprice) +- [kzgCommitments](BlobEIP4844TxData.md#kzgcommitments) +- [kzgProof](BlobEIP4844TxData.md#kzgproof) +- [maxFeePerDataGas](BlobEIP4844TxData.md#maxfeeperdatagas) +- [maxFeePerGas](BlobEIP4844TxData.md#maxfeepergas) +- [maxPriorityFeePerGas](BlobEIP4844TxData.md#maxpriorityfeepergas) +- [nonce](BlobEIP4844TxData.md#nonce) +- [r](BlobEIP4844TxData.md#r) +- [s](BlobEIP4844TxData.md#s) +- [to](BlobEIP4844TxData.md#to) +- [type](BlobEIP4844TxData.md#type) +- [v](BlobEIP4844TxData.md#v) +- [value](BlobEIP4844TxData.md#value) +- [versionedHashes](BlobEIP4844TxData.md#versionedhashes) + +## Properties + +### accessList + +• `Optional` **accessList**: ``null`` \| [`AccessListBuffer`](../README.md#accesslistbuffer) \| [`AccessList`](../README.md#accesslist) + +The access list which contains the addresses/storage slots which the transaction wishes to access + +#### Inherited from + +[FeeMarketEIP1559TxData](FeeMarketEIP1559TxData.md).[accessList](FeeMarketEIP1559TxData.md#accesslist) + +#### Defined in + +[types.ts:214](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L214) + +___ + +### blobs + +• `Optional` **blobs**: `BufferLike`[] + +The blobs associated with a transaction + +#### Defined in + +[types.ts:251](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L251) + +___ + +### chainId + +• `Optional` **chainId**: `BigIntLike` + +The transaction's chain ID + +#### Inherited from + +[FeeMarketEIP1559TxData](FeeMarketEIP1559TxData.md).[chainId](FeeMarketEIP1559TxData.md#chainid) + +#### Defined in + +[types.ts:209](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L209) + +___ + +### data + +• `Optional` **data**: `BufferLike` + +This will contain the data of the message or the init of a contract. + +#### Inherited from + +[FeeMarketEIP1559TxData](FeeMarketEIP1559TxData.md).[data](FeeMarketEIP1559TxData.md#data) + +#### Defined in + +[types.ts:178](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L178) + +___ + +### gasLimit + +• `Optional` **gasLimit**: `BigIntLike` + +The transaction's gas limit. + +#### Inherited from + +[FeeMarketEIP1559TxData](FeeMarketEIP1559TxData.md).[gasLimit](FeeMarketEIP1559TxData.md#gaslimit) + +#### Defined in + +[types.ts:163](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L163) + +___ + +### gasPrice + +• `Optional` **gasPrice**: ``null`` + +The transaction's gas price, inherited from [Transaction](../classes/Transaction.md). This property is not used for EIP1559 +transactions and should always be undefined for this specific transaction type. + +#### Inherited from + +[FeeMarketEIP1559TxData](FeeMarketEIP1559TxData.md).[gasPrice](FeeMarketEIP1559TxData.md#gasprice) + +#### Defined in + +[types.ts:225](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L225) + +___ + +### kzgCommitments + +• `Optional` **kzgCommitments**: `BufferLike`[] + +The KZG commitments corresponding to the versioned hashes for each blob + +#### Defined in + +[types.ts:255](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L255) + +___ + +### kzgProof + +• `Optional` **kzgProof**: `BufferLike` + +The aggregate KZG proof associated with the transaction + +#### Defined in + +[types.ts:259](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L259) + +___ + +### maxFeePerDataGas + +• `Optional` **maxFeePerDataGas**: `BigIntLike` + +The maximum fee per data gas paid for the transaction + +#### Defined in + +[types.ts:247](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L247) + +___ + +### maxFeePerGas + +• `Optional` **maxFeePerGas**: `BigIntLike` + +The maximum total fee + +#### Inherited from + +[FeeMarketEIP1559TxData](FeeMarketEIP1559TxData.md).[maxFeePerGas](FeeMarketEIP1559TxData.md#maxfeepergas) + +#### Defined in + +[types.ts:233](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L233) + +___ + +### maxPriorityFeePerGas + +• `Optional` **maxPriorityFeePerGas**: `BigIntLike` + +The maximum inclusion fee per gas (this fee is given to the miner) + +#### Inherited from + +[FeeMarketEIP1559TxData](FeeMarketEIP1559TxData.md).[maxPriorityFeePerGas](FeeMarketEIP1559TxData.md#maxpriorityfeepergas) + +#### Defined in + +[types.ts:229](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L229) + +___ + +### nonce + +• `Optional` **nonce**: `BigIntLike` + +The transaction's nonce. + +#### Inherited from + +[FeeMarketEIP1559TxData](FeeMarketEIP1559TxData.md).[nonce](FeeMarketEIP1559TxData.md#nonce) + +#### Defined in + +[types.ts:153](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L153) + +___ + +### r + +• `Optional` **r**: `BigIntLike` + +EC signature parameter. + +#### Inherited from + +[FeeMarketEIP1559TxData](FeeMarketEIP1559TxData.md).[r](FeeMarketEIP1559TxData.md#r) + +#### Defined in + +[types.ts:188](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L188) + +___ + +### s + +• `Optional` **s**: `BigIntLike` + +EC signature parameter. + +#### Inherited from + +[FeeMarketEIP1559TxData](FeeMarketEIP1559TxData.md).[s](FeeMarketEIP1559TxData.md#s) + +#### Defined in + +[types.ts:193](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L193) + +___ + +### to + +• `Optional` **to**: `AddressLike` + +The transaction's the address is sent to. + +#### Inherited from + +[FeeMarketEIP1559TxData](FeeMarketEIP1559TxData.md).[to](FeeMarketEIP1559TxData.md#to) + +#### Defined in + +[types.ts:168](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L168) + +___ + +### type + +• `Optional` **type**: `BigIntLike` + +The transaction type + +#### Inherited from + +[FeeMarketEIP1559TxData](FeeMarketEIP1559TxData.md).[type](FeeMarketEIP1559TxData.md#type) + +#### Defined in + +[types.ts:199](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L199) + +___ + +### v + +• `Optional` **v**: `BigIntLike` + +EC recovery ID. + +#### Inherited from + +[FeeMarketEIP1559TxData](FeeMarketEIP1559TxData.md).[v](FeeMarketEIP1559TxData.md#v) + +#### Defined in + +[types.ts:183](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L183) + +___ + +### value + +• `Optional` **value**: `BigIntLike` + +The amount of Ether sent. + +#### Inherited from + +[FeeMarketEIP1559TxData](FeeMarketEIP1559TxData.md).[value](FeeMarketEIP1559TxData.md#value) + +#### Defined in + +[types.ts:173](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L173) + +___ + +### versionedHashes + +• `Optional` **versionedHashes**: `BufferLike`[] + +The versioned hashes used to validate the blobs attached to a transaction + +#### Defined in + +[types.ts:243](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L243) diff --git a/packages/tx/docs/interfaces/FeeMarketEIP1559TxData.md b/packages/tx/docs/interfaces/FeeMarketEIP1559TxData.md index b54b8acdae..f6635fae2e 100644 --- a/packages/tx/docs/interfaces/FeeMarketEIP1559TxData.md +++ b/packages/tx/docs/interfaces/FeeMarketEIP1559TxData.md @@ -10,6 +10,8 @@ ↳ **`FeeMarketEIP1559TxData`** + ↳↳ [`BlobEIP4844TxData`](BlobEIP4844TxData.md) + ## Table of contents ### Properties @@ -33,7 +35,7 @@ ### accessList -• `Optional` **accessList**: [`AccessListBuffer`](../README.md#accesslistbuffer) \| [`AccessList`](../README.md#accesslist) +• `Optional` **accessList**: ``null`` \| [`AccessListBuffer`](../README.md#accesslistbuffer) \| [`AccessList`](../README.md#accesslist) The access list which contains the addresses/storage slots which the transaction wishes to access @@ -43,7 +45,7 @@ The access list which contains the addresses/storage slots which the transaction #### Defined in -[types.ts:178](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L178) +[types.ts:214](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L214) ___ @@ -59,7 +61,7 @@ The transaction's chain ID #### Defined in -[types.ts:173](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L173) +[types.ts:209](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L209) ___ @@ -75,7 +77,7 @@ This will contain the data of the message or the init of a contract. #### Defined in -[types.ts:142](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L142) +[types.ts:178](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L178) ___ @@ -91,13 +93,13 @@ The transaction's gas limit. #### Defined in -[types.ts:127](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L127) +[types.ts:163](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L163) ___ ### gasPrice -• `Optional` **gasPrice**: `undefined` +• `Optional` **gasPrice**: ``null`` The transaction's gas price, inherited from [Transaction](../classes/Transaction.md). This property is not used for EIP1559 transactions and should always be undefined for this specific transaction type. @@ -108,7 +110,7 @@ transactions and should always be undefined for this specific transaction type. #### Defined in -[types.ts:189](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L189) +[types.ts:225](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L225) ___ @@ -120,7 +122,7 @@ The maximum total fee #### Defined in -[types.ts:197](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L197) +[types.ts:233](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L233) ___ @@ -132,7 +134,7 @@ The maximum inclusion fee per gas (this fee is given to the miner) #### Defined in -[types.ts:193](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L193) +[types.ts:229](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L229) ___ @@ -148,7 +150,7 @@ The transaction's nonce. #### Defined in -[types.ts:117](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L117) +[types.ts:153](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L153) ___ @@ -164,7 +166,7 @@ EC signature parameter. #### Defined in -[types.ts:152](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L152) +[types.ts:188](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L188) ___ @@ -180,7 +182,7 @@ EC signature parameter. #### Defined in -[types.ts:157](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L157) +[types.ts:193](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L193) ___ @@ -196,7 +198,7 @@ The transaction's the address is sent to. #### Defined in -[types.ts:132](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L132) +[types.ts:168](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L168) ___ @@ -212,7 +214,7 @@ The transaction type #### Defined in -[types.ts:163](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L163) +[types.ts:199](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L199) ___ @@ -228,7 +230,7 @@ EC recovery ID. #### Defined in -[types.ts:147](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L147) +[types.ts:183](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L183) ___ @@ -244,4 +246,4 @@ The amount of Ether sent. #### Defined in -[types.ts:137](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L137) +[types.ts:173](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L173) diff --git a/packages/tx/docs/interfaces/JsonRpcTx.md b/packages/tx/docs/interfaces/JsonRpcTx.md index aa053de216..fa8ac8a35f 100644 --- a/packages/tx/docs/interfaces/JsonRpcTx.md +++ b/packages/tx/docs/interfaces/JsonRpcTx.md @@ -15,6 +15,7 @@ - [gasPrice](JsonRpcTx.md#gasprice) - [hash](JsonRpcTx.md#hash) - [input](JsonRpcTx.md#input) +- [maxFeePerDataGas](JsonRpcTx.md#maxfeeperdatagas) - [maxFeePerGas](JsonRpcTx.md#maxfeepergas) - [maxPriorityFeePerGas](JsonRpcTx.md#maxpriorityfeepergas) - [nonce](JsonRpcTx.md#nonce) @@ -25,6 +26,7 @@ - [type](JsonRpcTx.md#type) - [v](JsonRpcTx.md#v) - [value](JsonRpcTx.md#value) +- [versionedHashes](JsonRpcTx.md#versionedhashes) ## Properties @@ -34,7 +36,7 @@ #### Defined in -[types.ts:279](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L279) +[types.ts:343](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L343) ___ @@ -44,7 +46,7 @@ ___ #### Defined in -[types.ts:271](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L271) +[types.ts:335](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L335) ___ @@ -54,7 +56,7 @@ ___ #### Defined in -[types.ts:272](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L272) +[types.ts:336](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L336) ___ @@ -64,7 +66,7 @@ ___ #### Defined in -[types.ts:280](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L280) +[types.ts:344](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L344) ___ @@ -74,7 +76,7 @@ ___ #### Defined in -[types.ts:273](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L273) +[types.ts:337](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L337) ___ @@ -84,7 +86,7 @@ ___ #### Defined in -[types.ts:274](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L274) +[types.ts:338](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L338) ___ @@ -94,7 +96,7 @@ ___ #### Defined in -[types.ts:275](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L275) +[types.ts:339](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L339) ___ @@ -104,7 +106,7 @@ ___ #### Defined in -[types.ts:281](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L281) +[types.ts:345](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L345) ___ @@ -114,7 +116,17 @@ ___ #### Defined in -[types.ts:282](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L282) +[types.ts:346](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L346) + +___ + +### maxFeePerDataGas + +• `Optional` **maxFeePerDataGas**: `string` + +#### Defined in + +[types.ts:354](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L354) ___ @@ -124,7 +136,7 @@ ___ #### Defined in -[types.ts:276](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L276) +[types.ts:340](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L340) ___ @@ -134,7 +146,7 @@ ___ #### Defined in -[types.ts:277](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L277) +[types.ts:341](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L341) ___ @@ -144,7 +156,7 @@ ___ #### Defined in -[types.ts:283](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L283) +[types.ts:347](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L347) ___ @@ -154,7 +166,7 @@ ___ #### Defined in -[types.ts:288](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L288) +[types.ts:352](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L352) ___ @@ -164,7 +176,7 @@ ___ #### Defined in -[types.ts:289](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L289) +[types.ts:353](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L353) ___ @@ -174,7 +186,7 @@ ___ #### Defined in -[types.ts:284](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L284) +[types.ts:348](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L348) ___ @@ -184,7 +196,7 @@ ___ #### Defined in -[types.ts:285](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L285) +[types.ts:349](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L349) ___ @@ -194,7 +206,7 @@ ___ #### Defined in -[types.ts:278](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L278) +[types.ts:342](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L342) ___ @@ -204,7 +216,7 @@ ___ #### Defined in -[types.ts:287](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L287) +[types.ts:351](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L351) ___ @@ -214,4 +226,14 @@ ___ #### Defined in -[types.ts:286](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L286) +[types.ts:350](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L350) + +___ + +### versionedHashes + +• `Optional` **versionedHashes**: `string`[] + +#### Defined in + +[types.ts:355](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L355) diff --git a/packages/tx/docs/interfaces/JsonTx.md b/packages/tx/docs/interfaces/JsonTx.md index 97460dda12..b4234b09c5 100644 --- a/packages/tx/docs/interfaces/JsonTx.md +++ b/packages/tx/docs/interfaces/JsonTx.md @@ -18,6 +18,7 @@ and not all the values are present on all tx types - [data](JsonTx.md#data) - [gasLimit](JsonTx.md#gaslimit) - [gasPrice](JsonTx.md#gasprice) +- [maxFeePerDataGas](JsonTx.md#maxfeeperdatagas) - [maxFeePerGas](JsonTx.md#maxfeepergas) - [maxPriorityFeePerGas](JsonTx.md#maxpriorityfeepergas) - [nonce](JsonTx.md#nonce) @@ -27,6 +28,7 @@ and not all the values are present on all tx types - [type](JsonTx.md#type) - [v](JsonTx.md#v) - [value](JsonTx.md#value) +- [versionedHashes](JsonTx.md#versionedhashes) ## Properties @@ -36,7 +38,7 @@ and not all the values are present on all tx types #### Defined in -[types.ts:261](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L261) +[types.ts:323](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L323) ___ @@ -46,7 +48,7 @@ ___ #### Defined in -[types.ts:260](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L260) +[types.ts:322](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L322) ___ @@ -56,7 +58,7 @@ ___ #### Defined in -[types.ts:255](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L255) +[types.ts:317](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L317) ___ @@ -66,7 +68,7 @@ ___ #### Defined in -[types.ts:253](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L253) +[types.ts:315](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L315) ___ @@ -76,7 +78,17 @@ ___ #### Defined in -[types.ts:252](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L252) +[types.ts:314](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L314) + +___ + +### maxFeePerDataGas + +• `Optional` **maxFeePerDataGas**: `string` + +#### Defined in + +[types.ts:327](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L327) ___ @@ -86,7 +98,7 @@ ___ #### Defined in -[types.ts:264](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L264) +[types.ts:326](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L326) ___ @@ -96,7 +108,7 @@ ___ #### Defined in -[types.ts:263](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L263) +[types.ts:325](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L325) ___ @@ -106,7 +118,7 @@ ___ #### Defined in -[types.ts:251](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L251) +[types.ts:313](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L313) ___ @@ -116,7 +128,7 @@ ___ #### Defined in -[types.ts:257](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L257) +[types.ts:319](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L319) ___ @@ -126,7 +138,7 @@ ___ #### Defined in -[types.ts:258](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L258) +[types.ts:320](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L320) ___ @@ -136,7 +148,7 @@ ___ #### Defined in -[types.ts:254](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L254) +[types.ts:316](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L316) ___ @@ -146,7 +158,7 @@ ___ #### Defined in -[types.ts:262](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L262) +[types.ts:324](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L324) ___ @@ -156,7 +168,7 @@ ___ #### Defined in -[types.ts:256](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L256) +[types.ts:318](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L318) ___ @@ -166,4 +178,14 @@ ___ #### Defined in -[types.ts:259](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L259) +[types.ts:321](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L321) + +___ + +### versionedHashes + +• `Optional` **versionedHashes**: `string`[] + +#### Defined in + +[types.ts:328](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L328) diff --git a/packages/tx/docs/interfaces/TxOptions.md b/packages/tx/docs/interfaces/TxOptions.md index 6e095e6ebe..4ebc220223 100644 --- a/packages/tx/docs/interfaces/TxOptions.md +++ b/packages/tx/docs/interfaces/TxOptions.md @@ -8,11 +8,25 @@ The options for initializing a [Transaction](../classes/Transaction.md). ### Properties +- [allowUnlimitedInitCodeSize](TxOptions.md#allowunlimitedinitcodesize) - [common](TxOptions.md#common) - [freeze](TxOptions.md#freeze) ## Properties +### allowUnlimitedInitCodeSize + +• `Optional` **allowUnlimitedInitCodeSize**: `boolean` + +Allows unlimited contract code-size init while debugging. This (partially) disables EIP-3860. +Gas cost for initcode size analysis will still be charged. Use with caution. + +#### Defined in + +[types.ts:98](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L98) + +___ + ### common • `Optional` **common**: `Common` @@ -28,7 +42,7 @@ Current default hardfork: `istanbul` #### Defined in -[types.ts:51](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L51) +[types.ts:80](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L80) ___ @@ -48,4 +62,4 @@ Default: true #### Defined in -[types.ts:63](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L63) +[types.ts:92](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/tx/src/types.ts#L92) diff --git a/packages/tx/package.json b/packages/tx/package.json index 86d25ef3aa..176d95c9b3 100644 --- a/packages/tx/package.json +++ b/packages/tx/package.json @@ -1,6 +1,6 @@ { "name": "@ethereumjs/tx", - "version": "4.1.1", + "version": "4.1.2", "description": "A simple module for creating, manipulating and signing Ethereum transactions", "keywords": [ "ethereum", @@ -52,9 +52,9 @@ }, "dependencies": { "@chainsafe/ssz": "^0.11.1", - "@ethereumjs/common": "^3.1.1", + "@ethereumjs/common": "^3.1.2", "@ethereumjs/rlp": "^4.0.1", - "@ethereumjs/util": "^8.0.5", + "@ethereumjs/util": "^8.0.6", "ethereum-cryptography": "^2.0.0" }, "peerDependencies": { diff --git a/packages/util/CHANGELOG.md b/packages/util/CHANGELOG.md index a0a6b60d65..9749f5b605 100644 --- a/packages/util/CHANGELOG.md +++ b/packages/util/CHANGELOG.md @@ -6,6 +6,11 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) (modification: no type change headlines) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). +## 8.0.6 - 2023-04-20 + +- Bump `@chainsafe/ssz` dependency to 0.11.1 (no WASM, native SHA-256 implementation, ES2019 compatible, explicit imports), PRs [#2622](https://github.com/ethereumjs/ethereumjs-monorepo/pull/2622), [#2564](https://github.com/ethereumjs/ethereumjs-monorepo/pull/2564) and [#2656](https://github.com/ethereumjs/ethereumjs-monorepo/pull/2656) +- Update ethereum-cryptography from 1.2 to 2.0 (switch from noble-secp256k1 to noble-curves), PR [#2641](https://github.com/ethereumjs/ethereumjs-monorepo/pull/2641) + ## 8.0.5 - 2023-02-27 - Pinned `@chainsafe/ssz` dependency to `v0.9.4` due to ES2021 features used in `v0.10.+` causing compatibility issues, PR [#2555](https://github.com/ethereumjs/ethereumjs-monorepo/pull/2555) diff --git a/packages/util/docs/README.md b/packages/util/docs/README.md index 0183451e2e..106a52dc89 100644 --- a/packages/util/docs/README.md +++ b/packages/util/docs/README.md @@ -77,8 +77,11 @@ - [bufferToBigInt](README.md#buffertobigint) - [bufferToHex](README.md#buffertohex) - [bufferToInt](README.md#buffertoint) +- [bytesToNibbles](README.md#bytestonibbles) +- [compactBytesToNibbles](README.md#compactbytestonibbles) - [ecrecover](README.md#ecrecover) - [ecsign](README.md#ecsign) +- [fetchFromProvider](README.md#fetchfromprovider) - [fromAscii](README.md#fromascii) - [fromRpcSig](README.md#fromrpcsig) - [fromSigned](README.md#fromsigned) @@ -87,6 +90,8 @@ - [generateAddress2](README.md#generateaddress2) - [getBinarySize](README.md#getbinarysize) - [getKeys](README.md#getkeys) +- [getProvider](README.md#getprovider) +- [hasTerminator](README.md#hasterminator) - [hashPersonalMessage](README.md#hashpersonalmessage) - [importPublic](README.md#importpublic) - [intToBuffer](README.md#inttobuffer) @@ -100,6 +105,8 @@ - [isValidPublic](README.md#isvalidpublic) - [isValidSignature](README.md#isvalidsignature) - [isZeroAddress](README.md#iszeroaddress) +- [nibblesToBytes](README.md#nibblestobytes) +- [nibblesToCompactBytes](README.md#nibblestocompactbytes) - [padToEven](README.md#padtoeven) - [privateToAddress](README.md#privatetoaddress) - [privateToPublic](README.md#privatetopublic) @@ -279,7 +286,7 @@ Keccak-256 hash of null #### Defined in -[packages/util/src/constants.ts:39](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/util/src/constants.ts#L39) +[packages/util/src/constants.ts:43](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/util/src/constants.ts#L43) ___ @@ -291,7 +298,7 @@ Keccak-256 hash of null #### Defined in -[packages/util/src/constants.ts:34](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/util/src/constants.ts#L34) +[packages/util/src/constants.ts:38](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/util/src/constants.ts#L38) ___ @@ -303,7 +310,7 @@ Keccak-256 hash of the RLP of null #### Defined in -[packages/util/src/constants.ts:60](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/util/src/constants.ts#L60) +[packages/util/src/constants.ts:64](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/util/src/constants.ts#L64) ___ @@ -315,7 +322,7 @@ Keccak-256 of an RLP of an empty array #### Defined in -[packages/util/src/constants.ts:50](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/util/src/constants.ts#L50) +[packages/util/src/constants.ts:54](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/util/src/constants.ts#L54) ___ @@ -327,7 +334,7 @@ Keccak-256 of an RLP of an empty array #### Defined in -[packages/util/src/constants.ts:44](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/util/src/constants.ts#L44) +[packages/util/src/constants.ts:48](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/util/src/constants.ts#L48) ___ @@ -339,7 +346,7 @@ Keccak-256 hash of the RLP of null #### Defined in -[packages/util/src/constants.ts:55](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/util/src/constants.ts#L55) +[packages/util/src/constants.ts:59](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/util/src/constants.ts#L59) ___ @@ -360,10 +367,12 @@ ___ • `Const` **MAX\_INTEGER\_BIGINT**: `bigint` The max integer that the evm can handle (2^256-1) as a bigint +2^256-1 equals to 340282366920938463463374607431768211455 +We use literal value instead of calculated value for compatibility issue. #### Defined in -[packages/util/src/constants.ts:19](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/util/src/constants.ts#L19) +[packages/util/src/constants.ts:21](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/util/src/constants.ts#L21) ___ @@ -385,7 +394,7 @@ ___ #### Defined in -[packages/util/src/constants.ts:67](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/util/src/constants.ts#L67) +[packages/util/src/constants.ts:71](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/util/src/constants.ts#L71) ___ @@ -397,17 +406,17 @@ RLP encoded empty string #### Defined in -[packages/util/src/constants.ts:65](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/util/src/constants.ts#L65) +[packages/util/src/constants.ts:69](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/util/src/constants.ts#L69) ___ ### SECP256K1\_ORDER -• `Const` **SECP256K1\_ORDER**: `bigint` = `CURVE.n` +• `Const` **SECP256K1\_ORDER**: `bigint` = `secp256k1.CURVE.n` #### Defined in -[packages/util/src/constants.ts:21](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/util/src/constants.ts#L21) +[packages/util/src/constants.ts:25](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/util/src/constants.ts#L25) ___ @@ -417,7 +426,7 @@ ___ #### Defined in -[packages/util/src/constants.ts:22](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/util/src/constants.ts#L22) +[packages/util/src/constants.ts:26](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/util/src/constants.ts#L26) ___ @@ -429,7 +438,7 @@ ___ #### Defined in -[packages/util/src/constants.ts:27](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/util/src/constants.ts#L27) +[packages/util/src/constants.ts:31](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/util/src/constants.ts#L31) ## Functions @@ -449,7 +458,7 @@ ___ #### Defined in -[packages/util/src/account.ts:347](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/util/src/account.ts#L347) +[packages/util/src/account.ts:349](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/util/src/account.ts#L349) ___ @@ -457,22 +466,24 @@ ___ ▸ **accountBodyToRLP**(`body`, `couldBeSlim?`): `Buffer` -Converts a slim account RLP to a normal account RLP +Converts a slim account (per snap protocol spec) to the RLP encoded version of the account #### Parameters -| Name | Type | Default value | -| :------ | :------ | :------ | -| `body` | [`AccountBodyBuffer`](README.md#accountbodybuffer) | `undefined` | -| `couldBeSlim` | `boolean` | `true` | +| Name | Type | Default value | Description | +| :------ | :------ | :------ | :------ | +| `body` | [`AccountBodyBuffer`](README.md#accountbodybuffer) | `undefined` | Array of 4 Buffer-like items to represent the account | +| `couldBeSlim` | `boolean` | `true` | - | #### Returns `Buffer` +RLP encoded version of the account + #### Defined in -[packages/util/src/account.ts:371](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/util/src/account.ts#L371) +[packages/util/src/account.ts:375](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/util/src/account.ts#L375) ___ @@ -492,7 +503,7 @@ ___ #### Defined in -[packages/util/src/account.ts:358](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/util/src/account.ts#L358) +[packages/util/src/account.ts:360](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/util/src/account.ts#L360) ___ @@ -812,6 +823,46 @@ If the input number exceeds 53 bits. ___ +### bytesToNibbles + +▸ **bytesToNibbles**(`str`): `Uint8Array` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `str` | `Uint8Array` | + +#### Returns + +`Uint8Array` + +#### Defined in + +[packages/util/src/encoding.ts:40](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/util/src/encoding.ts#L40) + +___ + +### compactBytesToNibbles + +▸ **compactBytesToNibbles**(`compact`): `Uint8Array` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `compact` | `Uint8Array` | + +#### Returns + +`Uint8Array` + +#### Defined in + +[packages/util/src/encoding.ts:54](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/util/src/encoding.ts#L54) + +___ + ### ecrecover ▸ **ecrecover**(`msgHash`, `v`, `r`, `s`, `chainId?`): `Buffer` @@ -868,6 +919,27 @@ accordingly, otherwise return a "static" `v` just derived from the `recovery` bi ___ +### fetchFromProvider + +▸ **fetchFromProvider**(`url`, `params`): `Promise`<`any`\> + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `url` | `string` | +| `params` | `rpcParams` | + +#### Returns + +`Promise`<`any`\> + +#### Defined in + +[packages/util/src/provider.ts:7](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/util/src/provider.ts#L7) + +___ + ### fromAscii ▸ **fromAscii**(`stringValue`): `string` @@ -915,7 +987,7 @@ it's a signed message (EIP-191 or EIP-712) adding `27` at the end. Remove if nee #### Defined in -[packages/util/src/signature.ts:112](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/util/src/signature.ts#L112) +[packages/util/src/signature.ts:113](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/util/src/signature.ts#L113) ___ @@ -1070,6 +1142,49 @@ getKeys([{a: '1', b: '2'}, {a: '3', b: '4'}], 'a') => ['1', '3'] ___ +### getProvider + +▸ **getProvider**(`provider`): `any` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `provider` | `any` | + +#### Returns + +`any` + +#### Defined in + +[packages/util/src/provider.ts:24](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/util/src/provider.ts#L24) + +___ + +### hasTerminator + +▸ **hasTerminator**(`nibbles`): `boolean` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `nibbles` | `Uint8Array` | + +#### Returns + +`boolean` + +boolean indicating if input hex nibble sequence has terminator indicating leaf-node + terminator is represented with 16 because a nibble ranges from 0 - 15(f) + +#### Defined in + +[packages/util/src/encoding.ts:8](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/util/src/encoding.ts#L8) + +___ + ### hashPersonalMessage ▸ **hashPersonalMessage**(`message`): `Buffer` @@ -1091,7 +1206,7 @@ used to produce the signature. #### Defined in -[packages/util/src/signature.ts:189](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/util/src/signature.ts#L189) +[packages/util/src/signature.ts:190](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/util/src/signature.ts#L190) ___ @@ -1113,7 +1228,7 @@ Converts a public key to the Ethereum format. #### Defined in -[packages/util/src/account.ts:316](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/util/src/account.ts#L316) +[packages/util/src/account.ts:318](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/util/src/account.ts#L318) ___ @@ -1350,7 +1465,7 @@ NOTE: Accepts `v === 0 | v === 1` for EIP1559 transactions #### Defined in -[packages/util/src/signature.ts:149](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/util/src/signature.ts#L149) +[packages/util/src/signature.ts:150](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/util/src/signature.ts#L150) ___ @@ -1372,7 +1487,48 @@ Checks if a given address is the zero address. #### Defined in -[packages/util/src/account.ts:336](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/util/src/account.ts#L336) +[packages/util/src/account.ts:338](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/util/src/account.ts#L338) + +___ + +### nibblesToBytes + +▸ **nibblesToBytes**(`nibbles`, `bytes`): `void` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `nibbles` | `Uint8Array` | +| `bytes` | `Uint8Array` | + +#### Returns + +`void` + +#### Defined in + +[packages/util/src/encoding.ts:12](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/util/src/encoding.ts#L12) + +___ + +### nibblesToCompactBytes + +▸ **nibblesToCompactBytes**(`nibbles`): `Uint8Array` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `nibbles` | `Uint8Array` | + +#### Returns + +`Uint8Array` + +#### Defined in + +[packages/util/src/encoding.ts:18](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/util/src/encoding.ts#L18) ___ @@ -1418,7 +1574,7 @@ Returns the ethereum address of a given private key. #### Defined in -[packages/util/src/account.ts:309](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/util/src/account.ts#L309) +[packages/util/src/account.ts:311](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/util/src/account.ts#L311) ___ @@ -1700,7 +1856,7 @@ Signature #### Defined in -[packages/util/src/signature.ts:89](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/util/src/signature.ts#L89) +[packages/util/src/signature.ts:90](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/util/src/signature.ts#L90) ___ @@ -1728,7 +1884,7 @@ Signature #### Defined in -[packages/util/src/signature.ts:74](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/util/src/signature.ts#L74) +[packages/util/src/signature.ts:75](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/util/src/signature.ts#L75) ___ @@ -1983,7 +2139,7 @@ Returns the zero address. #### Defined in -[packages/util/src/account.ts:327](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/util/src/account.ts#L327) +[packages/util/src/account.ts:329](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/util/src/account.ts#L329) ___ diff --git a/packages/util/package.json b/packages/util/package.json index 2bfd322f07..53c4a3bc96 100644 --- a/packages/util/package.json +++ b/packages/util/package.json @@ -1,6 +1,6 @@ { "name": "@ethereumjs/util", - "version": "8.0.5", + "version": "8.0.6", "description": "A collection of utility functions for Ethereum", "keywords": [ "ethereum", diff --git a/packages/vm/CHANGELOG.md b/packages/vm/CHANGELOG.md index 77f2ff8824..775d92c74e 100644 --- a/packages/vm/CHANGELOG.md +++ b/packages/vm/CHANGELOG.md @@ -6,6 +6,21 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) (modification: no type change headlines) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). +## 6.4.2 - 2023-04-20 + +### Features + +- Diff-based Touched Accounts Checkpointing (fixes performance/memory bottlenecks), PR [#2581](https://github.com/ethereumjs/ethereumjs-monorepo/pull/2581) + +### Bugfixes + +- Cleanup touched accounts after withdrawals, PR [#2601](https://github.com/ethereumjs/ethereumjs-monorepo/pull/2601) + +### Maintenance + +- Update ethereum-cryptography from 1.2 to 2.0 (switch from noble-secp256k1 to noble-curves), PR [#2641](https://github.com/ethereumjs/ethereumjs-monorepo/pull/2641) +- Bump `@ethereumjs/util` `@chainsafe/ssz` dependency to 0.11.1 (no WASM, native SHA-256 implementation, ES2019 compatible, explicit imports), PRs [#2622](https://github.com/ethereumjs/ethereumjs-monorepo/pull/2622), [#2564](https://github.com/ethereumjs/ethereumjs-monorepo/pull/2564) and [#2656](https://github.com/ethereumjs/ethereumjs-monorepo/pull/2656) + ## 6.4.1 - 2023-02-27 - Pinned `@ethereumjs/util` `@chainsafe/ssz` dependency to `v0.9.4` due to ES2021 features used in `v0.10.+` causing compatibility issues, PR [#2555](https://github.com/ethereumjs/ethereumjs-monorepo/pull/2555) diff --git a/packages/vm/docs/README.md b/packages/vm/docs/README.md index 7c70a10156..dca5b2b1b6 100644 --- a/packages/vm/docs/README.md +++ b/packages/vm/docs/README.md @@ -58,7 +58,7 @@ ___ #### Defined in -[vm/src/types.ts:276](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/vm/src/types.ts#L276) +[vm/src/types.ts:281](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/vm/src/types.ts#L281) ___ @@ -68,7 +68,7 @@ ___ #### Defined in -[vm/src/types.ts:364](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/vm/src/types.ts#L364) +[vm/src/types.ts:380](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/vm/src/types.ts#L380) ___ @@ -138,7 +138,7 @@ ___ #### Defined in -[vm/src/types.ts:249](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/vm/src/types.ts#L249) +[vm/src/types.ts:254](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/vm/src/types.ts#L254) ___ @@ -148,7 +148,7 @@ ___ #### Defined in -[vm/src/types.ts:284](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/vm/src/types.ts#L284) +[vm/src/types.ts:289](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/vm/src/types.ts#L289) ___ @@ -158,7 +158,7 @@ ___ #### Defined in -[vm/src/types.ts:330](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/vm/src/types.ts#L330) +[vm/src/types.ts:341](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/vm/src/types.ts#L341) ___ diff --git a/packages/vm/package.json b/packages/vm/package.json index 71584c942a..8f3b4559eb 100644 --- a/packages/vm/package.json +++ b/packages/vm/package.json @@ -1,6 +1,6 @@ { "name": "@ethereumjs/vm", - "version": "6.4.1", + "version": "6.4.2", "description": "An Ethereum VM implementation", "keywords": [ "ethereum", @@ -56,15 +56,15 @@ "tsc": "../../config/cli/ts-compile.sh" }, "dependencies": { - "@ethereumjs/block": "^4.2.1", - "@ethereumjs/blockchain": "^6.2.1", - "@ethereumjs/common": "^3.1.1", - "@ethereumjs/evm": "^1.3.1", + "@ethereumjs/block": "^4.2.2", + "@ethereumjs/blockchain": "^6.2.2", + "@ethereumjs/common": "^3.1.2", + "@ethereumjs/evm": "^1.3.2", "@ethereumjs/rlp": "^4.0.1", - "@ethereumjs/statemanager": "^1.0.4", - "@ethereumjs/trie": "^5.0.4", - "@ethereumjs/tx": "^4.1.1", - "@ethereumjs/util": "^8.0.5", + "@ethereumjs/statemanager": "^1.0.5", + "@ethereumjs/trie": "^5.0.5", + "@ethereumjs/tx": "^4.1.2", + "@ethereumjs/util": "^8.0.6", "debug": "^4.3.3", "ethereum-cryptography": "^2.0.0", "mcl-wasm": "^0.7.1", From a70516cfc7c63444f4187610dc9f6b0c925f2b55 Mon Sep 17 00:00:00 2001 From: Micah Zoltu Date: Sun, 30 Apr 2023 00:25:42 +0800 Subject: [PATCH 45/53] tx: Fix EIP-155 transaction encoding on chain ID 0 When preparing Ethereum data for RLP encoding, you must convert all values to either byte arrays or lists. Scalar values (positive integers) are converted to byte arrays by using the fewest bytes possible to represent the value in big endian format. The canonical form of any scalar value prepped for RLP encoding is that any leading `0` bytes stripped. In the case of `0`, this means that the only byte (`0x00`) is stripped and you are left with an empty array. Most of the values in this code are properly 0-stripped using `bigIntToUnpaddedBuffer`. Unfortunately, it appears that the `chainId` was added without stripping leading zeros. In most cases this doesn't matter, but if someone is running a chainId 0 blockchain and they want to EIP-155 encode their transaction, the previous code would result in an invalid transaction because only the canonical form is allowed. This change fixes this bug and correctly prepares the chainId in EIP-155 transactions for RLP encoding. --- packages/tx/src/legacyTransaction.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/tx/src/legacyTransaction.ts b/packages/tx/src/legacyTransaction.ts index 3933de928d..b6f69453e3 100644 --- a/packages/tx/src/legacyTransaction.ts +++ b/packages/tx/src/legacyTransaction.ts @@ -189,7 +189,7 @@ export class Transaction extends BaseTransaction { ] if (this.supports(Capability.EIP155ReplayProtection)) { - values.push(toBytes(this.common.chainId())) + values.push(bigIntToUnpaddedBytes(this.common.chainId())) values.push(unpadBytes(toBytes(0))) values.push(unpadBytes(toBytes(0))) } From c2eff0e380ff59f3f499225f1f8a80d0925d8834 Mon Sep 17 00:00:00 2001 From: mitic2023 <129968170+mitic2023@users.noreply.github.com> Date: Fri, 5 May 2023 22:17:45 +0800 Subject: [PATCH 46/53] Update README.md (#2679) --- packages/tx/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/tx/README.md b/packages/tx/README.md index 801cc9c355..a5bf9beb29 100644 --- a/packages/tx/README.md +++ b/packages/tx/README.md @@ -92,7 +92,7 @@ const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.London, eip This library supports the following transaction types ([EIP-2718](https://eips.ethereum.org/EIPS/eip-2718)): -- `BlobEIP4844Transaction` ([EIP-4844](https://eips.ethereumorg/EIPS/eip-4844), proto-danksharding) +- `BlobEIP4844Transaction` ([EIP-4844](https://eips.ethereum.org/EIPS/eip-4844), proto-danksharding) - `FeeMarketEIP1559Transaction` ([EIP-1559](https://eips.ethereum.org/EIPS/eip-1559), gas fee market) - `AccessListEIP2930Transaction` ([EIP-2930](https://eips.ethereum.org/EIPS/eip-2930), optional access lists) - `Transaction`, the Ethereum standard tx up to `berlin`, now referred to as legacy txs with the introduction of tx types From c66504192b466ffa730b381a947365477292ab5c Mon Sep 17 00:00:00 2001 From: Pulasthi Bandara Date: Wed, 10 May 2023 19:18:07 +1200 Subject: [PATCH 47/53] Fix link for running EVM code in browser (#2682) --- packages/evm/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/evm/README.md b/packages/evm/README.md index 95917dfb1c..1cc4ae928e 100644 --- a/packages/evm/README.md +++ b/packages/evm/README.md @@ -113,7 +113,7 @@ The [@ethereumjs/vm](https://github.com/ethereumjs/ethereumjs-monorepo/tree/mast ## Browser -To build the EVM for standalone use in the browser, see: [Running the EVM in a browser](https://github.com/ethereumjs/ethereumjs-monorepo/tree/master/packages/evm/examples/run-code-browser.js). +To build the EVM for standalone use in the browser, see: [Running the EVM in a browser](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/evm/examples/runCode.ts). ## Setup From 90789dfcb687b145a94366508f9b57644a43ead1 Mon Sep 17 00:00:00 2001 From: Holger Drewes Date: Wed, 10 May 2023 12:10:51 +0200 Subject: [PATCH 48/53] Monorepo: Remove Dynamic Node Versions check / Fix Test Runs (#2683) * Monorepo: remove dynamic external node version check, statically set to 16,18,20 * Remove get-node-versions entirely * Remove pull request trigger --------- Co-authored-by: acolytec3 <17355484+acolytec3@users.noreply.github.com> --- .github/workflows/node-versions.yml | 43 ++--------------------------- 1 file changed, 3 insertions(+), 40 deletions(-) diff --git a/.github/workflows/node-versions.yml b/.github/workflows/node-versions.yml index a30616f682..d472f16cf0 100644 --- a/.github/workflows/node-versions.yml +++ b/.github/workflows/node-versions.yml @@ -1,6 +1,3 @@ -# This special file aims to run node tests for each relevant node version. -# A relevant node version can be: active, current, maintenance or EOL with some months of tolerance -# For more details, please check https://github.com/evertonfraga/testable-node-versions name: Node versions on: schedule: @@ -8,24 +5,11 @@ on: workflow_dispatch: jobs: - get-node-versions: - runs-on: ubuntu-latest - outputs: - matrix: ${{ steps.set-matrix.outputs.matrix }} - steps: - - uses: actions/setup-node@v2 - with: - node-version: 16 - - - id: set-matrix - run: echo "::set-output name=matrix::$(npx testable-node-versions)" - tests: - needs: get-node-versions runs-on: ubuntu-latest strategy: matrix: - node: ${{ fromJson(needs.get-node-versions.outputs.matrix) }} + node-version: [16,18,20] fail-fast: false steps: - uses: actions/checkout@v3 @@ -35,81 +19,60 @@ jobs: - name: Use Node.js ${{ matrix.node-version }} uses: actions/setup-node@v2 with: - node-version: ${{ matrix.node }} + node-version: ${{ matrix.node-version }} cache: 'npm' - run: npm ci - # Added a check to ensure we only run on NodeJS 14 or later to all jobs until the `node-testable-versions` script stops picking up 12. - - name: Test Block run: npm run test working-directory: packages/block - if: ${{ matrix.node >= 16 }} - name: Test Blockchain run: npm run test working-directory: packages/blockchain - if: ${{ matrix.node >= 16 }} - - # Client and Devp2p temporarily disabled for Node < 15 due to browser build - # error along node-versions CI run "TextDecoder is not defined" triggered in - # older Noder versions (Node 12/14) - # https://github.com/ethereumjs/ethereumjs-monorepo/pull/1305 - # 2021-06-18 - # + # Switch client to unit tests only due to `async_hooks` dependency build error in browser tests: 2022-06-15 - name: Test Client run: npm run test:unit working-directory: packages/client - if: ${{ matrix.node >= 16 }} - name: Test Devp2p run: npm run test working-directory: packages/devp2p - if: ${{ matrix.node >= 16 }} - name: Test Common run: npm run test working-directory: packages/common - if: ${{ matrix.node >= 16 }} - name: Test Ethash run: npm run test working-directory: packages/ethash - if: ${{ matrix.node >= 16 }} - name: Test EVM run: npm run test working-directory: packages/evm - if: ${{ matrix.node >= 16 }} - name: Test Trie run: npm run test working-directory: packages/trie - if: ${{ matrix.node >= 16 }} - name: Test Tx run: npm run test working-directory: packages/tx - if: ${{ matrix.node >= 16 }} - name: Test Util run: npm run test working-directory: packages/util - if: ${{ matrix.node >= 16 }} - name: Test StateManager run: npm run test working-directory: packages/statemanager - if: ${{ matrix.node >= 16 }} - name: Test VM run: npm run test:API working-directory: packages/vm - if: ${{ matrix.node >= 16 }} - name: Test RLP run: npm run test working-directory: packages/rlp - if: ${{ matrix.node >= 16 }} From 690368a46c223ab3f828376a6f3c7ba1533b7fa9 Mon Sep 17 00:00:00 2001 From: Gabriel Rocheleau Date: Thu, 11 May 2023 09:18:55 -0400 Subject: [PATCH 49/53] trie: update references to old deleteFromDB constructor arg (#2695) --- packages/trie/README.md | 2 +- packages/trie/docs/classes/Trie.md | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/trie/README.md b/packages/trie/README.md index 5907bd233d..f87cfd26a8 100644 --- a/packages/trie/README.md +++ b/packages/trie/README.md @@ -91,7 +91,7 @@ const trie = new Trie({ db: new LevelDB(new Level('MY_TRIE_DB_LOCATION')) }) #### Node Deletion (Pruning) -By default, the deletion of trie nodes from the underlying database does not occur in order to avoid corrupting older trie states (as of `v4.2.0`). Should you only wish to work with the latest state of a trie, you can switch to a delete behavior (for example, if you wish to save disk space) by using the `deleteFromDB` constructor option (see related release notes in the changelog for further details). +By default, the deletion of trie nodes from the underlying database does not occur in order to avoid corrupting older trie states (as of `v4.2.0`). Should you only wish to work with the latest state of a trie, you can switch to a delete behavior (for example, if you wish to save disk space) by using the `useNodePruning` constructor option (see related release notes in the changelog for further details). #### Root Persistence diff --git a/packages/trie/docs/classes/Trie.md b/packages/trie/docs/classes/Trie.md index 39d7ec498a..536d370719 100644 --- a/packages/trie/docs/classes/Trie.md +++ b/packages/trie/docs/classes/Trie.md @@ -78,7 +78,7 @@ The root for an empty trie ▸ **batch**(`ops`): `Promise`<`void`\> The given hash of operations (key additions or deletions) are executed on the trie -(delete operations are only executed on DB with `deleteFromDB` set to `true`) +(delete operations are only executed on DB with `useNodePruning` set to `true`) **`Example`** @@ -256,7 +256,7 @@ ___ ▸ **del**(`key`): `Promise`<`void`\> Deletes a value given a `key` from the trie -(delete operations are only executed on DB with `deleteFromDB` set to `true`) +(delete operations are only executed on DB with `useNodePruning` set to `true`) #### Parameters @@ -422,7 +422,7 @@ ___ ▸ **put**(`key`, `value`): `Promise`<`void`\> Stores a given `value` at the given `key` or do a delete if `value` is empty -(delete operations are only executed on DB with `deleteFromDB` set to `true`) +(delete operations are only executed on DB with `useNodePruning` set to `true`) #### Parameters From 82c35bbb053afbfc9de72f94068a2a0c80193c6d Mon Sep 17 00:00:00 2001 From: acolytec3 <17355484+acolytec3@users.noreply.github.com> Date: Fri, 12 May 2023 11:11:36 -0400 Subject: [PATCH 50/53] Add package-lock back --- package-lock.json | 30594 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 30594 insertions(+) create mode 100644 package-lock.json diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000000..1a4d7d7594 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,30594 @@ +{ + "name": "root", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "root", + "hasInstallScript": true, + "workspaces": [ + "packages/*" + ], + "devDependencies": { + "@types/node": "16.11.49", + "@types/tape": "4.13.2", + "@typescript-eslint/eslint-plugin": "5.33.1", + "@typescript-eslint/parser": "5.33.1", + "c8": "7.12.0", + "eslint": "8.22.0", + "eslint-config-prettier": "8.5.0", + "eslint-config-typestrict": "1.0.5", + "eslint-formatter-codeframe": "7.32.1", + "eslint-plugin-ethereumjs": "file:./eslint", + "eslint-plugin-github": "4.3.7", + "eslint-plugin-implicit-dependencies": "1.1.1", + "eslint-plugin-import": "2.26.0", + "eslint-plugin-prettier": "4.2.1", + "eslint-plugin-simple-import-sort": "7.0.0", + "eslint-plugin-sonarjs": "0.14.0", + "karma": "6.4.0", + "karma-chrome-launcher": "3.1.1", + "karma-firefox-launcher": "2.1.2", + "karma-tap": "4.2.0", + "karma-typescript": "5.5.3", + "karma-typescript-es6-transform": "5.5.3", + "lint-staged": "13.0.3", + "prettier": "2.7.1", + "sort-package-json": "1.57.0", + "tape": "5.6.0", + "ts-node": "10.9.1", + "typedoc": "0.23.10", + "typedoc-plugin-markdown": "3.13.4", + "typescript": "4.7.4" + }, + "engines": { + "node": ">=14", + "npm": ">=7" + } + }, + "eslint": { + "dev": true + }, + "node_modules/@ampproject/remapping": { + "version": "2.2.0", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jridgewell/gen-mapping": "^0.1.0", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.12.11", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/highlight": "^7.10.4" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.19.4", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.19.6", + "dev": true, + "license": "MIT", + "dependencies": { + "@ampproject/remapping": "^2.1.0", + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.19.6", + "@babel/helper-compilation-targets": "^7.19.3", + "@babel/helper-module-transforms": "^7.19.6", + "@babel/helpers": "^7.19.4", + "@babel/parser": "^7.19.6", + "@babel/template": "^7.18.10", + "@babel/traverse": "^7.19.6", + "@babel/types": "^7.19.4", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.1", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/@babel/code-frame": { + "version": "7.18.6", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/highlight": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core/node_modules/convert-source-map": { + "version": "1.9.0", + "dev": true, + "license": "MIT" + }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.0", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/generator": { + "version": "7.19.6", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.19.4", + "@jridgewell/gen-mapping": "^0.3.2", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/generator/node_modules/@jridgewell/gen-mapping": { + "version": "0.3.2", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.18.6", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.18.9", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-explode-assignable-expression": "^7.18.6", + "@babel/types": "^7.18.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.19.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.19.3", + "@babel/helper-validator-option": "^7.18.6", + "browserslist": "^4.21.3", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.0", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.19.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.19.0", + "@babel/helper-member-expression-to-functions": "^7.18.9", + "@babel/helper-optimise-call-expression": "^7.18.6", + "@babel/helper-replace-supers": "^7.18.9", + "@babel/helper-split-export-declaration": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin": { + "version": "7.19.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "regexpu-core": "^5.1.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.3.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-compilation-targets": "^7.17.7", + "@babel/helper-plugin-utils": "^7.16.7", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2", + "semver": "^6.1.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0-0" + } + }, + "node_modules/@babel/helper-define-polyfill-provider/node_modules/semver": { + "version": "6.3.0", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-environment-visitor": { + "version": "7.18.9", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-explode-assignable-expression": { + "version": "7.18.6", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-function-name": { + "version": "7.19.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.18.10", + "@babel/types": "^7.19.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-hoist-variables": { + "version": "7.18.6", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.18.9", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.18.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.18.6", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.19.6", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-module-imports": "^7.18.6", + "@babel/helper-simple-access": "^7.19.4", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/helper-validator-identifier": "^7.19.1", + "@babel/template": "^7.18.10", + "@babel/traverse": "^7.19.6", + "@babel/types": "^7.19.4" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.18.6", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.19.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-remap-async-to-generator": { + "version": "7.18.9", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-wrap-function": "^7.18.9", + "@babel/types": "^7.18.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-replace-supers": { + "version": "7.19.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-member-expression-to-functions": "^7.18.9", + "@babel/helper-optimise-call-expression": "^7.18.6", + "@babel/traverse": "^7.19.1", + "@babel/types": "^7.19.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-simple-access": { + "version": "7.19.4", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.19.4" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.18.9", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.18.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.18.6", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.19.4", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.19.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.18.6", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-wrap-function": { + "version": "7.19.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-function-name": "^7.19.0", + "@babel/template": "^7.18.10", + "@babel/traverse": "^7.19.0", + "@babel/types": "^7.19.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.19.4", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.18.10", + "@babel/traverse": "^7.19.4", + "@babel/types": "^7.19.4" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.18.6", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.18.6", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/color-convert": { + "version": "1.9.3", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/highlight/node_modules/color-name": { + "version": "1.1.3", + "dev": true, + "license": "MIT" + }, + "node_modules/@babel/highlight/node_modules/has-flag": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/parser": { + "version": "7.19.6", + "dev": true, + "license": "MIT", + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.18.6", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.18.9", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.18.9", + "@babel/plugin-proposal-optional-chaining": "^7.18.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.13.0" + } + }, + "node_modules/@babel/plugin-proposal-async-generator-functions": { + "version": "7.19.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-plugin-utils": "^7.19.0", + "@babel/helper-remap-async-to-generator": "^7.18.9", + "@babel/plugin-syntax-async-generators": "^7.8.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-class-properties": { + "version": "7.18.6", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-class-static-block": { + "version": "7.18.6", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-class-static-block": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.12.0" + } + }, + "node_modules/@babel/plugin-proposal-dynamic-import": { + "version": "7.18.6", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-dynamic-import": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-export-namespace-from": { + "version": "7.18.9", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-json-strings": { + "version": "7.18.6", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-json-strings": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-logical-assignment-operators": { + "version": "7.18.9", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-nullish-coalescing-operator": { + "version": "7.18.6", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-numeric-separator": { + "version": "7.18.6", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-object-rest-spread": { + "version": "7.19.4", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.19.4", + "@babel/helper-compilation-targets": "^7.19.3", + "@babel/helper-plugin-utils": "^7.19.0", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.18.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-optional-catch-binding": { + "version": "7.18.6", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-optional-chaining": { + "version": "7.18.9", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.18.9", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-private-methods": { + "version": "7.18.6", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-private-property-in-object": { + "version": "7.18.6", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-create-class-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-unicode-property-regex": { + "version": "7.18.6", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-export-namespace-from": { + "version": "7.8.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-assertions": { + "version": "7.18.6", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-arrow-functions": { + "version": "7.18.6", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-to-generator": { + "version": "7.18.6", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/helper-remap-async-to-generator": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoped-functions": { + "version": "7.18.6", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoping": { + "version": "7.19.4", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.19.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-classes": { + "version": "7.19.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-compilation-targets": "^7.19.0", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.19.0", + "@babel/helper-optimise-call-expression": "^7.18.6", + "@babel/helper-plugin-utils": "^7.19.0", + "@babel/helper-replace-supers": "^7.18.9", + "@babel/helper-split-export-declaration": "^7.18.6", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-classes/node_modules/globals": { + "version": "11.12.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/plugin-transform-computed-properties": { + "version": "7.18.9", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-destructuring": { + "version": "7.19.4", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.19.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-dotall-regex": { + "version": "7.18.6", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-duplicate-keys": { + "version": "7.18.9", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-exponentiation-operator": { + "version": "7.18.6", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-for-of": { + "version": "7.18.8", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-function-name": { + "version": "7.18.9", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-compilation-targets": "^7.18.9", + "@babel/helper-function-name": "^7.18.9", + "@babel/helper-plugin-utils": "^7.18.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-literals": { + "version": "7.18.9", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-member-expression-literals": { + "version": "7.18.6", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-amd": { + "version": "7.19.6", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-transforms": "^7.19.6", + "@babel/helper-plugin-utils": "^7.19.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-commonjs": { + "version": "7.19.6", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-transforms": "^7.19.6", + "@babel/helper-plugin-utils": "^7.19.0", + "@babel/helper-simple-access": "^7.19.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-systemjs": { + "version": "7.19.6", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-hoist-variables": "^7.18.6", + "@babel/helper-module-transforms": "^7.19.6", + "@babel/helper-plugin-utils": "^7.19.0", + "@babel/helper-validator-identifier": "^7.19.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-umd": { + "version": "7.18.6", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-transforms": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.19.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.19.0", + "@babel/helper-plugin-utils": "^7.19.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-new-target": { + "version": "7.18.6", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-super": { + "version": "7.18.6", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/helper-replace-supers": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-parameters": { + "version": "7.18.8", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-property-literals": { + "version": "7.18.6", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-regenerator": { + "version": "7.18.6", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6", + "regenerator-transform": "^0.15.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-reserved-words": { + "version": "7.18.6", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-shorthand-properties": { + "version": "7.18.6", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-spread": { + "version": "7.19.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.19.0", + "@babel/helper-skip-transparent-expression-wrappers": "^7.18.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-sticky-regex": { + "version": "7.18.6", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-template-literals": { + "version": "7.18.9", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typeof-symbol": { + "version": "7.18.9", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-escapes": { + "version": "7.18.10", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-regex": { + "version": "7.18.6", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-env": { + "version": "7.19.4", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.19.4", + "@babel/helper-compilation-targets": "^7.19.3", + "@babel/helper-plugin-utils": "^7.19.0", + "@babel/helper-validator-option": "^7.18.6", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.18.6", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.18.9", + "@babel/plugin-proposal-async-generator-functions": "^7.19.1", + "@babel/plugin-proposal-class-properties": "^7.18.6", + "@babel/plugin-proposal-class-static-block": "^7.18.6", + "@babel/plugin-proposal-dynamic-import": "^7.18.6", + "@babel/plugin-proposal-export-namespace-from": "^7.18.9", + "@babel/plugin-proposal-json-strings": "^7.18.6", + "@babel/plugin-proposal-logical-assignment-operators": "^7.18.9", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.18.6", + "@babel/plugin-proposal-numeric-separator": "^7.18.6", + "@babel/plugin-proposal-object-rest-spread": "^7.19.4", + "@babel/plugin-proposal-optional-catch-binding": "^7.18.6", + "@babel/plugin-proposal-optional-chaining": "^7.18.9", + "@babel/plugin-proposal-private-methods": "^7.18.6", + "@babel/plugin-proposal-private-property-in-object": "^7.18.6", + "@babel/plugin-proposal-unicode-property-regex": "^7.18.6", + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3", + "@babel/plugin-syntax-import-assertions": "^7.18.6", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5", + "@babel/plugin-transform-arrow-functions": "^7.18.6", + "@babel/plugin-transform-async-to-generator": "^7.18.6", + "@babel/plugin-transform-block-scoped-functions": "^7.18.6", + "@babel/plugin-transform-block-scoping": "^7.19.4", + "@babel/plugin-transform-classes": "^7.19.0", + "@babel/plugin-transform-computed-properties": "^7.18.9", + "@babel/plugin-transform-destructuring": "^7.19.4", + "@babel/plugin-transform-dotall-regex": "^7.18.6", + "@babel/plugin-transform-duplicate-keys": "^7.18.9", + "@babel/plugin-transform-exponentiation-operator": "^7.18.6", + "@babel/plugin-transform-for-of": "^7.18.8", + "@babel/plugin-transform-function-name": "^7.18.9", + "@babel/plugin-transform-literals": "^7.18.9", + "@babel/plugin-transform-member-expression-literals": "^7.18.6", + "@babel/plugin-transform-modules-amd": "^7.18.6", + "@babel/plugin-transform-modules-commonjs": "^7.18.6", + "@babel/plugin-transform-modules-systemjs": "^7.19.0", + "@babel/plugin-transform-modules-umd": "^7.18.6", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.19.1", + "@babel/plugin-transform-new-target": "^7.18.6", + "@babel/plugin-transform-object-super": "^7.18.6", + "@babel/plugin-transform-parameters": "^7.18.8", + "@babel/plugin-transform-property-literals": "^7.18.6", + "@babel/plugin-transform-regenerator": "^7.18.6", + "@babel/plugin-transform-reserved-words": "^7.18.6", + "@babel/plugin-transform-shorthand-properties": "^7.18.6", + "@babel/plugin-transform-spread": "^7.19.0", + "@babel/plugin-transform-sticky-regex": "^7.18.6", + "@babel/plugin-transform-template-literals": "^7.18.9", + "@babel/plugin-transform-typeof-symbol": "^7.18.9", + "@babel/plugin-transform-unicode-escapes": "^7.18.10", + "@babel/plugin-transform-unicode-regex": "^7.18.6", + "@babel/preset-modules": "^0.1.5", + "@babel/types": "^7.19.4", + "babel-plugin-polyfill-corejs2": "^0.3.3", + "babel-plugin-polyfill-corejs3": "^0.6.0", + "babel-plugin-polyfill-regenerator": "^0.4.1", + "core-js-compat": "^3.25.1", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-env/node_modules/semver": { + "version": "6.3.0", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/preset-modules": { + "version": "0.1.5", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", + "@babel/plugin-transform-dotall-regex": "^7.4.4", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.19.4", + "dev": true, + "license": "MIT", + "dependencies": { + "regenerator-runtime": "^0.13.4" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/runtime-corejs3": { + "version": "7.19.6", + "dev": true, + "license": "MIT", + "dependencies": { + "core-js-pure": "^3.25.1", + "regenerator-runtime": "^0.13.4" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.18.10", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.18.6", + "@babel/parser": "^7.18.10", + "@babel/types": "^7.18.10" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template/node_modules/@babel/code-frame": { + "version": "7.18.6", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/highlight": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.19.6", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.19.6", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.19.0", + "@babel/helper-hoist-variables": "^7.18.6", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/parser": "^7.19.6", + "@babel/types": "^7.19.4", + "debug": "^4.1.0", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse/node_modules/@babel/code-frame": { + "version": "7.18.6", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/highlight": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse/node_modules/globals": { + "version": "11.12.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/types": { + "version": "7.19.4", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.19.4", + "@babel/helper-validator-identifier": "^7.19.1", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "dev": true, + "license": "MIT" + }, + "node_modules/@chainsafe/as-sha256": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@chainsafe/as-sha256/-/as-sha256-0.4.1.tgz", + "integrity": "sha512-IqeeGwQihK6Y2EYLFofqs2eY2ep1I2MvQXHzOAI+5iQN51OZlUkrLgyAugu2x86xZewDk5xas7lNczkzFzF62w==" + }, + "node_modules/@chainsafe/libp2p-noise": { + "version": "4.1.2", + "license": "MIT", + "dependencies": { + "@stablelib/chacha20poly1305": "^1.0.1", + "@stablelib/hkdf": "^1.0.1", + "@stablelib/sha256": "^1.0.1", + "@stablelib/x25519": "^1.0.1", + "debug": "^4.3.1", + "it-buffer": "^0.1.3", + "it-length-prefixed": "^5.0.3", + "it-pair": "^1.0.0", + "it-pb-rpc": "^0.1.11", + "it-pipe": "^1.1.0", + "libp2p-crypto": "^0.19.7", + "peer-id": "^0.15.3", + "protobufjs": "^6.11.2", + "uint8arrays": "^3.0.0" + } + }, + "node_modules/@chainsafe/libp2p-noise/node_modules/err-code": { + "version": "3.0.1", + "license": "MIT" + }, + "node_modules/@chainsafe/libp2p-noise/node_modules/peer-id": { + "version": "0.15.4", + "license": "MIT", + "dependencies": { + "class-is": "^1.1.0", + "libp2p-crypto": "^0.20.0", + "minimist": "^1.2.5", + "multiformats": "^9.4.5", + "protobufjs": "^6.10.2", + "uint8arrays": "^3.0.0" + }, + "bin": { + "peer-id": "src/bin.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@chainsafe/libp2p-noise/node_modules/peer-id/node_modules/libp2p-crypto": { + "version": "0.20.0", + "license": "MIT", + "dependencies": { + "err-code": "^3.0.1", + "iso-random-stream": "^2.0.0", + "keypair": "^1.0.4", + "multiformats": "^9.4.5", + "noble-ed25519": "^1.2.6", + "noble-secp256k1": "^1.2.10", + "node-forge": "^0.10.0", + "pem-jwk": "^2.0.0", + "protobufjs": "^6.11.2", + "uint8arrays": "^3.0.0", + "ursa-optional": "^0.10.1" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/@chainsafe/persistent-merkle-tree": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/@chainsafe/persistent-merkle-tree/-/persistent-merkle-tree-0.6.1.tgz", + "integrity": "sha512-gcENLemRR13+1MED2NeZBMA7FRS0xQPM7L2vhMqvKkjqtFT4YfjSVADq5U0iLuQLhFUJEMVuA8fbv5v+TN6O9A==", + "dependencies": { + "@chainsafe/as-sha256": "^0.4.1", + "@noble/hashes": "^1.3.0" + } + }, + "node_modules/@chainsafe/ssz": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/@chainsafe/ssz/-/ssz-0.11.1.tgz", + "integrity": "sha512-cB8dBkgGN6ZoeOKuk+rIRHKN0L5i9JLGeC0Lui71QX0TuLcQKwgbfkUexpyJxnGFatWf8yeJxlOjozMn/OTP0g==", + "dependencies": { + "@chainsafe/as-sha256": "^0.4.1", + "@chainsafe/persistent-merkle-tree": "^0.6.1" + } + }, + "node_modules/@colors/colors": { + "version": "1.5.0", + "license": "MIT", + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@dabh/diagnostics": { + "version": "2.0.3", + "license": "MIT", + "dependencies": { + "colorspace": "1.1.x", + "enabled": "2.0.x", + "kuler": "^2.0.0" + } + }, + "node_modules/@discoveryjs/json-ext": { + "version": "0.5.7", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "1.3.3", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.4.0", + "globals": "^13.15.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@ethereumjs/block": { + "resolved": "packages/block", + "link": true + }, + "node_modules/@ethereumjs/blockchain": { + "resolved": "packages/blockchain", + "link": true + }, + "node_modules/@ethereumjs/client": { + "resolved": "packages/client", + "link": true + }, + "node_modules/@ethereumjs/common": { + "resolved": "packages/common", + "link": true + }, + "node_modules/@ethereumjs/devp2p": { + "resolved": "packages/devp2p", + "link": true + }, + "node_modules/@ethereumjs/ethash": { + "resolved": "packages/ethash", + "link": true + }, + "node_modules/@ethereumjs/evm": { + "resolved": "packages/evm", + "link": true + }, + "node_modules/@ethereumjs/rlp": { + "resolved": "packages/rlp", + "link": true + }, + "node_modules/@ethereumjs/statemanager": { + "resolved": "packages/statemanager", + "link": true + }, + "node_modules/@ethereumjs/trie": { + "resolved": "packages/trie", + "link": true + }, + "node_modules/@ethereumjs/tx": { + "resolved": "packages/tx", + "link": true + }, + "node_modules/@ethereumjs/util": { + "resolved": "packages/util", + "link": true + }, + "node_modules/@ethereumjs/vm": { + "resolved": "packages/vm", + "link": true + }, + "node_modules/@ethersproject/abi": { + "version": "5.7.0", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/address": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/constants": "^5.7.0", + "@ethersproject/hash": "^5.7.0", + "@ethersproject/keccak256": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/strings": "^5.7.0" + } + }, + "node_modules/@ethersproject/abstract-provider": { + "version": "5.7.0", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/networks": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/transactions": "^5.7.0", + "@ethersproject/web": "^5.7.0" + } + }, + "node_modules/@ethersproject/abstract-signer": { + "version": "5.7.0", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/abstract-provider": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0" + } + }, + "node_modules/@ethersproject/address": { + "version": "5.7.0", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/keccak256": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/rlp": "^5.7.0" + } + }, + "node_modules/@ethersproject/base64": { + "version": "5.7.0", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/bytes": "^5.7.0" + } + }, + "node_modules/@ethersproject/basex": { + "version": "5.7.0", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/properties": "^5.7.0" + } + }, + "node_modules/@ethersproject/bignumber": { + "version": "5.7.0", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "bn.js": "^5.2.1" + } + }, + "node_modules/@ethersproject/bytes": { + "version": "5.7.0", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/logger": "^5.7.0" + } + }, + "node_modules/@ethersproject/constants": { + "version": "5.7.0", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/bignumber": "^5.7.0" + } + }, + "node_modules/@ethersproject/contracts": { + "version": "5.7.0", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/abi": "^5.7.0", + "@ethersproject/abstract-provider": "^5.7.0", + "@ethersproject/abstract-signer": "^5.7.0", + "@ethersproject/address": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/constants": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/transactions": "^5.7.0" + } + }, + "node_modules/@ethersproject/hash": { + "version": "5.7.0", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/abstract-signer": "^5.7.0", + "@ethersproject/address": "^5.7.0", + "@ethersproject/base64": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/keccak256": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/strings": "^5.7.0" + } + }, + "node_modules/@ethersproject/hdnode": { + "version": "5.7.0", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/abstract-signer": "^5.7.0", + "@ethersproject/basex": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/pbkdf2": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/sha2": "^5.7.0", + "@ethersproject/signing-key": "^5.7.0", + "@ethersproject/strings": "^5.7.0", + "@ethersproject/transactions": "^5.7.0", + "@ethersproject/wordlists": "^5.7.0" + } + }, + "node_modules/@ethersproject/json-wallets": { + "version": "5.7.0", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/abstract-signer": "^5.7.0", + "@ethersproject/address": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/hdnode": "^5.7.0", + "@ethersproject/keccak256": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/pbkdf2": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/random": "^5.7.0", + "@ethersproject/strings": "^5.7.0", + "@ethersproject/transactions": "^5.7.0", + "aes-js": "3.0.0", + "scrypt-js": "3.0.1" + } + }, + "node_modules/@ethersproject/keccak256": { + "version": "5.7.0", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/bytes": "^5.7.0", + "js-sha3": "0.8.0" + } + }, + "node_modules/@ethersproject/logger": { + "version": "5.7.0", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT" + }, + "node_modules/@ethersproject/networks": { + "version": "5.7.1", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/logger": "^5.7.0" + } + }, + "node_modules/@ethersproject/pbkdf2": { + "version": "5.7.0", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/sha2": "^5.7.0" + } + }, + "node_modules/@ethersproject/properties": { + "version": "5.7.0", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/logger": "^5.7.0" + } + }, + "node_modules/@ethersproject/providers": { + "version": "5.7.2", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/abstract-provider": "^5.7.0", + "@ethersproject/abstract-signer": "^5.7.0", + "@ethersproject/address": "^5.7.0", + "@ethersproject/base64": "^5.7.0", + "@ethersproject/basex": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/constants": "^5.7.0", + "@ethersproject/hash": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/networks": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/random": "^5.7.0", + "@ethersproject/rlp": "^5.7.0", + "@ethersproject/sha2": "^5.7.0", + "@ethersproject/strings": "^5.7.0", + "@ethersproject/transactions": "^5.7.0", + "@ethersproject/web": "^5.7.0", + "bech32": "1.1.4", + "ws": "7.4.6" + } + }, + "node_modules/@ethersproject/providers/node_modules/ws": { + "version": "7.4.6", + "license": "MIT", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/@ethersproject/random": { + "version": "5.7.0", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0" + } + }, + "node_modules/@ethersproject/rlp": { + "version": "5.7.0", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0" + } + }, + "node_modules/@ethersproject/sha2": { + "version": "5.7.0", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "hash.js": "1.1.7" + } + }, + "node_modules/@ethersproject/signing-key": { + "version": "5.7.0", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "bn.js": "^5.2.1", + "elliptic": "6.5.4", + "hash.js": "1.1.7" + } + }, + "node_modules/@ethersproject/solidity": { + "version": "5.7.0", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/keccak256": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/sha2": "^5.7.0", + "@ethersproject/strings": "^5.7.0" + } + }, + "node_modules/@ethersproject/strings": { + "version": "5.7.0", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/constants": "^5.7.0", + "@ethersproject/logger": "^5.7.0" + } + }, + "node_modules/@ethersproject/transactions": { + "version": "5.7.0", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/address": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/constants": "^5.7.0", + "@ethersproject/keccak256": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/rlp": "^5.7.0", + "@ethersproject/signing-key": "^5.7.0" + } + }, + "node_modules/@ethersproject/units": { + "version": "5.7.0", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/constants": "^5.7.0", + "@ethersproject/logger": "^5.7.0" + } + }, + "node_modules/@ethersproject/wallet": { + "version": "5.7.0", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/abstract-provider": "^5.7.0", + "@ethersproject/abstract-signer": "^5.7.0", + "@ethersproject/address": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/hash": "^5.7.0", + "@ethersproject/hdnode": "^5.7.0", + "@ethersproject/json-wallets": "^5.7.0", + "@ethersproject/keccak256": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/random": "^5.7.0", + "@ethersproject/signing-key": "^5.7.0", + "@ethersproject/transactions": "^5.7.0", + "@ethersproject/wordlists": "^5.7.0" + } + }, + "node_modules/@ethersproject/web": { + "version": "5.7.1", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/base64": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/strings": "^5.7.0" + } + }, + "node_modules/@ethersproject/wordlists": { + "version": "5.7.0", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/hash": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/strings": "^5.7.0" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.10.7", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanwhocodes/object-schema": "^1.2.1", + "debug": "^4.1.1", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/gitignore-to-minimatch": { + "version": "1.0.2", + "dev": true, + "license": "Apache-2.0", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "1.2.1", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "dev": true, + "license": "ISC", + "dependencies": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": { + "version": "1.0.10", + "dev": true, + "license": "MIT", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { + "version": "4.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { + "version": "3.14.1", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": { + "version": "2.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { + "version": "4.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/sprintf-js": { + "version": "1.0.3", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.1.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/set-array": "^1.0.0", + "@jridgewell/sourcemap-codec": "^1.4.10" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.1.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.2", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "node_modules/@jridgewell/source-map/node_modules/@jridgewell/gen-mapping": { + "version": "0.3.2", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.14", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.17", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "3.1.0", + "@jridgewell/sourcemap-codec": "1.4.14" + } + }, + "node_modules/@motrix/nat-api": { + "version": "0.3.2", + "license": "MIT", + "dependencies": { + "async": "^3.2.0", + "debug": "^4.3.1", + "default-gateway": "^6.0.3", + "request": "^2.88.2", + "unordered-array-remove": "^1.0.2", + "xml2js": "^0.4.23" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/@multiformats/base-x": { + "version": "4.0.1", + "license": "MIT" + }, + "node_modules/@noble/curves": { + "version": "1.0.0", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "license": "MIT", + "dependencies": { + "@noble/hashes": "1.3.0" + } + }, + "node_modules/@noble/ed25519": { + "version": "1.7.1", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "license": "MIT" + }, + "node_modules/@noble/hashes": { + "version": "1.3.0", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "license": "MIT" + }, + "node_modules/@noble/secp256k1": { + "version": "1.6.3", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "license": "MIT" + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@protobufjs/aspromise": { + "version": "1.1.2", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/base64": { + "version": "1.1.2", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/codegen": { + "version": "2.0.4", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/eventemitter": { + "version": "1.1.0", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/fetch": { + "version": "1.1.0", + "license": "BSD-3-Clause", + "dependencies": { + "@protobufjs/aspromise": "^1.1.1", + "@protobufjs/inquire": "^1.1.0" + } + }, + "node_modules/@protobufjs/float": { + "version": "1.0.2", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/inquire": { + "version": "1.1.0", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/path": { + "version": "1.1.2", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/pool": { + "version": "1.1.0", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/utf8": { + "version": "1.1.0", + "license": "BSD-3-Clause" + }, + "node_modules/@scure/base": { + "version": "1.1.1", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "license": "MIT" + }, + "node_modules/@scure/bip32": { + "version": "1.3.0", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "license": "MIT", + "dependencies": { + "@noble/curves": "~1.0.0", + "@noble/hashes": "~1.3.0", + "@scure/base": "~1.1.0" + } + }, + "node_modules/@scure/bip39": { + "version": "1.2.0", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "license": "MIT", + "dependencies": { + "@noble/hashes": "~1.3.0", + "@scure/base": "~1.1.0" + } + }, + "node_modules/@sinonjs/commons": { + "version": "1.8.3", + "license": "BSD-3-Clause", + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "6.0.1", + "license": "BSD-3-Clause", + "dependencies": { + "@sinonjs/commons": "^1.7.0" + } + }, + "node_modules/@sinonjs/samsam": { + "version": "5.3.1", + "license": "BSD-3-Clause", + "dependencies": { + "@sinonjs/commons": "^1.6.0", + "lodash.get": "^4.4.2", + "type-detect": "^4.0.8" + } + }, + "node_modules/@sinonjs/text-encoding": { + "version": "0.7.2", + "license": "(Unlicense OR Apache-2.0)" + }, + "node_modules/@socket.io/component-emitter": { + "version": "3.1.0", + "dev": true, + "license": "MIT" + }, + "node_modules/@stablelib/aead": { + "version": "1.0.1", + "license": "MIT" + }, + "node_modules/@stablelib/binary": { + "version": "1.0.1", + "license": "MIT", + "dependencies": { + "@stablelib/int": "^1.0.1" + } + }, + "node_modules/@stablelib/bytes": { + "version": "1.0.1", + "license": "MIT" + }, + "node_modules/@stablelib/chacha": { + "version": "1.0.1", + "license": "MIT", + "dependencies": { + "@stablelib/binary": "^1.0.1", + "@stablelib/wipe": "^1.0.1" + } + }, + "node_modules/@stablelib/chacha20poly1305": { + "version": "1.0.1", + "license": "MIT", + "dependencies": { + "@stablelib/aead": "^1.0.1", + "@stablelib/binary": "^1.0.1", + "@stablelib/chacha": "^1.0.1", + "@stablelib/constant-time": "^1.0.1", + "@stablelib/poly1305": "^1.0.1", + "@stablelib/wipe": "^1.0.1" + } + }, + "node_modules/@stablelib/constant-time": { + "version": "1.0.1", + "license": "MIT" + }, + "node_modules/@stablelib/hash": { + "version": "1.0.1", + "license": "MIT" + }, + "node_modules/@stablelib/hkdf": { + "version": "1.0.1", + "license": "MIT", + "dependencies": { + "@stablelib/hash": "^1.0.1", + "@stablelib/hmac": "^1.0.1", + "@stablelib/wipe": "^1.0.1" + } + }, + "node_modules/@stablelib/hmac": { + "version": "1.0.1", + "license": "MIT", + "dependencies": { + "@stablelib/constant-time": "^1.0.1", + "@stablelib/hash": "^1.0.1", + "@stablelib/wipe": "^1.0.1" + } + }, + "node_modules/@stablelib/int": { + "version": "1.0.1", + "license": "MIT" + }, + "node_modules/@stablelib/keyagreement": { + "version": "1.0.1", + "license": "MIT", + "dependencies": { + "@stablelib/bytes": "^1.0.1" + } + }, + "node_modules/@stablelib/poly1305": { + "version": "1.0.1", + "license": "MIT", + "dependencies": { + "@stablelib/constant-time": "^1.0.1", + "@stablelib/wipe": "^1.0.1" + } + }, + "node_modules/@stablelib/random": { + "version": "1.0.2", + "license": "MIT", + "dependencies": { + "@stablelib/binary": "^1.0.1", + "@stablelib/wipe": "^1.0.1" + } + }, + "node_modules/@stablelib/sha256": { + "version": "1.0.1", + "license": "MIT", + "dependencies": { + "@stablelib/binary": "^1.0.1", + "@stablelib/hash": "^1.0.1", + "@stablelib/wipe": "^1.0.1" + } + }, + "node_modules/@stablelib/wipe": { + "version": "1.0.1", + "license": "MIT" + }, + "node_modules/@stablelib/x25519": { + "version": "1.0.3", + "license": "MIT", + "dependencies": { + "@stablelib/keyagreement": "^1.0.1", + "@stablelib/random": "^1.0.2", + "@stablelib/wipe": "^1.0.1" + } + }, + "node_modules/@tsconfig/node10": { + "version": "1.0.9", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.3", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/async": { + "version": "2.4.2", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/benchmark": { + "version": "1.0.33", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/bl": { + "version": "2.1.0", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/bn.js": { + "version": "5.1.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/body-parser": { + "version": "1.19.2", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/chalk": { + "version": "2.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "*" + } + }, + "node_modules/@types/connect": { + "version": "3.4.35", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/cookie": { + "version": "0.4.1", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/cookiejar": { + "version": "2.1.2", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/core-js": { + "version": "2.5.5", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/cors": { + "version": "2.8.12", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/debug": { + "version": "4.1.7", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/ms": "*" + } + }, + "node_modules/@types/eslint": { + "version": "8.4.7", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "node_modules/@types/eslint-scope": { + "version": "3.7.4", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, + "node_modules/@types/estree": { + "version": "0.0.51", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/fs-extra": { + "version": "9.0.13", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/glob": { + "version": "7.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/minimatch": "*", + "@types/node": "*" + } + }, + "node_modules/@types/ip": { + "version": "1.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.4", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/json-schema": { + "version": "7.0.11", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/json5": { + "version": "0.0.29", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/jwt-simple": { + "version": "0.5.33", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/k-bucket": { + "version": "5.0.1", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/level-errors": { + "version": "3.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/long": { + "version": "4.0.2", + "license": "MIT" + }, + "node_modules/@types/minimatch": { + "version": "3.0.5", + "license": "MIT" + }, + "node_modules/@types/minimist": { + "version": "1.2.2", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/ms": { + "version": "0.7.31", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "16.11.49", + "license": "MIT" + }, + "node_modules/@types/node-dir": { + "version": "0.0.34", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/readable-stream": { + "version": "2.3.14", + "license": "MIT", + "dependencies": { + "@types/node": "*", + "safe-buffer": "*" + } + }, + "node_modules/@types/retry": { + "version": "0.12.0", + "license": "MIT" + }, + "node_modules/@types/secp256k1": { + "version": "4.0.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/superagent": { + "version": "4.1.15", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/cookiejar": "*", + "@types/node": "*" + } + }, + "node_modules/@types/supertest": { + "version": "2.0.12", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/superagent": "*" + } + }, + "node_modules/@types/tape": { + "version": "4.13.2", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/ws": { + "version": "7.4.7", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/yargs": { + "version": "17.0.24", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "5.33.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/scope-manager": "5.33.1", + "@typescript-eslint/type-utils": "5.33.1", + "@typescript-eslint/utils": "5.33.1", + "debug": "^4.3.4", + "functional-red-black-tree": "^1.0.1", + "ignore": "^5.2.0", + "regexpp": "^3.2.0", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^5.0.0", + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "5.33.1", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@typescript-eslint/scope-manager": "5.33.1", + "@typescript-eslint/types": "5.33.1", + "@typescript-eslint/typescript-estree": "5.33.1", + "debug": "^4.3.4" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "5.33.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "5.33.1", + "@typescript-eslint/visitor-keys": "5.33.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "5.33.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/utils": "5.33.1", + "debug": "^4.3.4", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/types": { + "version": "5.33.1", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "5.33.1", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@typescript-eslint/types": "5.33.1", + "@typescript-eslint/visitor-keys": "5.33.1", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "5.33.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/json-schema": "^7.0.9", + "@typescript-eslint/scope-manager": "5.33.1", + "@typescript-eslint/types": "5.33.1", + "@typescript-eslint/typescript-estree": "5.33.1", + "eslint-scope": "^5.1.1", + "eslint-utils": "^3.0.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "5.33.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "5.33.1", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@webassemblyjs/ast": { + "version": "1.11.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/helper-numbers": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1" + } + }, + "node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.11.1", + "dev": true, + "license": "MIT" + }, + "node_modules/@webassemblyjs/helper-api-error": { + "version": "1.11.1", + "dev": true, + "license": "MIT" + }, + "node_modules/@webassemblyjs/helper-buffer": { + "version": "1.11.1", + "dev": true, + "license": "MIT" + }, + "node_modules/@webassemblyjs/helper-numbers": { + "version": "1.11.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/floating-point-hex-parser": "1.11.1", + "@webassemblyjs/helper-api-error": "1.11.1", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.11.1", + "dev": true, + "license": "MIT" + }, + "node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.11.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1" + } + }, + "node_modules/@webassemblyjs/ieee754": { + "version": "1.11.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "node_modules/@webassemblyjs/leb128": { + "version": "1.11.1", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/utf8": { + "version": "1.11.1", + "dev": true, + "license": "MIT" + }, + "node_modules/@webassemblyjs/wasm-edit": { + "version": "1.11.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/helper-wasm-section": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1", + "@webassemblyjs/wasm-opt": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1", + "@webassemblyjs/wast-printer": "1.11.1" + } + }, + "node_modules/@webassemblyjs/wasm-gen": { + "version": "1.11.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/ieee754": "1.11.1", + "@webassemblyjs/leb128": "1.11.1", + "@webassemblyjs/utf8": "1.11.1" + } + }, + "node_modules/@webassemblyjs/wasm-opt": { + "version": "1.11.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1" + } + }, + "node_modules/@webassemblyjs/wasm-parser": { + "version": "1.11.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-api-error": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/ieee754": "1.11.1", + "@webassemblyjs/leb128": "1.11.1", + "@webassemblyjs/utf8": "1.11.1" + } + }, + "node_modules/@webassemblyjs/wast-printer": { + "version": "1.11.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.11.1", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webpack-cli/configtest": { + "version": "1.2.0", + "dev": true, + "license": "MIT", + "peerDependencies": { + "webpack": "4.x.x || 5.x.x", + "webpack-cli": "4.x.x" + } + }, + "node_modules/@webpack-cli/info": { + "version": "1.5.0", + "dev": true, + "license": "MIT", + "dependencies": { + "envinfo": "^7.7.3" + }, + "peerDependencies": { + "webpack-cli": "4.x.x" + } + }, + "node_modules/@webpack-cli/serve": { + "version": "1.7.0", + "dev": true, + "license": "MIT", + "peerDependencies": { + "webpack-cli": "4.x.x" + }, + "peerDependenciesMeta": { + "webpack-dev-server": { + "optional": true + } + } + }, + "node_modules/@xtuc/ieee754": { + "version": "1.2.0", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@xtuc/long": { + "version": "4.2.2", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/@zxing/text-encoding": { + "version": "0.9.0", + "license": "(Unlicense OR Apache-2.0)", + "optional": true + }, + "node_modules/0x": { + "version": "4.11.0", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.9.2", + "browserify": "^16.2.3", + "concat-stream": "^1.5.2", + "d3-fg": "^6.14.0", + "debounce": "^1.2.0", + "debug": "^4.1.1", + "end-of-stream": "^1.1.0", + "env-string": "^1.0.0", + "escape-string-regexp": "^1.0.5", + "execspawn": "^1.0.1", + "has-unicode": "^2.0.1", + "hsl-to-rgb-for-reals": "^1.1.0", + "jsonstream2": "^1.1.2", + "make-dir": "^1.3.0", + "minimist": "^1.2.0", + "morphdom": "^2.3.3", + "nanohtml": "^1.4.0", + "on-net-listen": "^1.1.0", + "opn": "^5.4.0", + "perf-sym": "^2.0.3", + "pump": "^3.0.0", + "pumpify": "^1.4.0", + "semver": "^5.5.1", + "single-line-log": "^1.0.1", + "split2": "^3.1.0", + "tachyons": "^4.9.1", + "through2": "^2.0.5", + "which": "^1.2.4" + }, + "bin": { + "0x": "cmd.js" + }, + "engines": { + "node": ">=8.5.0" + } + }, + "node_modules/0x/node_modules/semver": { + "version": "5.7.1", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/abort-controller": { + "version": "3.0.0", + "license": "MIT", + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, + "node_modules/abortable-iterator": { + "version": "3.0.2", + "license": "MIT", + "dependencies": { + "get-iterator": "^1.0.2" + } + }, + "node_modules/abstract-level": { + "version": "1.0.3", + "license": "MIT", + "dependencies": { + "buffer": "^6.0.3", + "catering": "^2.1.0", + "is-buffer": "^2.0.5", + "level-supports": "^4.0.0", + "level-transcoder": "^1.0.1", + "module-error": "^1.0.1", + "queue-microtask": "^1.2.3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/abstract-leveldown": { + "version": "7.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer": "^6.0.3", + "catering": "^2.0.0", + "is-buffer": "^2.0.5", + "level-concat-iterator": "^3.0.0", + "level-supports": "^2.0.1", + "queue-microtask": "^1.2.3" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/abstract-leveldown/node_modules/level-supports": { + "version": "2.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/accepts": { + "version": "1.3.8", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.8.0", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-import-assertions": { + "version": "1.8.0", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^8" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/acorn-node": { + "version": "1.8.2", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "acorn": "^7.0.0", + "acorn-walk": "^7.0.0", + "xtend": "^4.0.2" + } + }, + "node_modules/acorn-node/node_modules/acorn": { + "version": "7.4.1", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "7.2.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/aes-js": { + "version": "3.0.0", + "license": "MIT" + }, + "node_modules/aggregate-error": { + "version": "3.1.0", + "license": "MIT", + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-keywords": { + "version": "3.5.2", + "dev": true, + "license": "MIT", + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-escapes/node_modules/type-fest": { + "version": "0.21.3", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/ansicolors": { + "version": "0.2.1", + "dev": true, + "license": "MIT" + }, + "node_modules/any-signal": { + "version": "2.1.2", + "license": "MIT", + "dependencies": { + "abort-controller": "^3.0.0", + "native-abort-controller": "^1.0.3" + } + }, + "node_modules/anymatch": { + "version": "3.1.2", + "dev": true, + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/append-transform": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "default-require-extensions": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/archy": { + "version": "1.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/arg": { + "version": "4.1.3", + "dev": true, + "license": "MIT" + }, + "node_modules/argparse": { + "version": "2.0.1", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/aria-query": { + "version": "4.2.2", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@babel/runtime": "^7.10.2", + "@babel/runtime-corejs3": "^7.10.2" + }, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/array-includes": { + "version": "3.1.5", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.19.5", + "get-intrinsic": "^1.1.1", + "is-string": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-union": { + "version": "2.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/array.prototype.every": { + "version": "1.1.3", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.0", + "is-string": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.find": { + "version": "2.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.4", + "es-shim-unscopables": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flat": { + "version": "1.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.2", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/asap": { + "version": "2.0.6", + "dev": true, + "license": "MIT" + }, + "node_modules/asn1": { + "version": "0.2.6", + "license": "MIT", + "dependencies": { + "safer-buffer": "~2.1.0" + } + }, + "node_modules/asn1.js": { + "version": "5.4.1", + "license": "MIT", + "dependencies": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "safer-buffer": "^2.1.0" + } + }, + "node_modules/asn1.js/node_modules/bn.js": { + "version": "4.12.0", + "license": "MIT" + }, + "node_modules/assert": { + "version": "1.5.0", + "dev": true, + "license": "MIT", + "dependencies": { + "object-assign": "^4.1.1", + "util": "0.10.3" + } + }, + "node_modules/assert-plus": { + "version": "1.0.0", + "license": "MIT", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/assert/node_modules/inherits": { + "version": "2.0.1", + "dev": true, + "license": "ISC" + }, + "node_modules/assert/node_modules/util": { + "version": "0.10.3", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "2.0.1" + } + }, + "node_modules/assertion-error": { + "version": "1.1.0", + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/ast-types-flow": { + "version": "0.0.7", + "dev": true, + "license": "ISC" + }, + "node_modules/astral-regex": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/async": { + "version": "3.2.4", + "license": "MIT" + }, + "node_modules/asynckit": { + "version": "0.4.0", + "license": "MIT" + }, + "node_modules/atomic-sleep": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.5", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/aws-sign2": { + "version": "0.7.0", + "license": "Apache-2.0", + "engines": { + "node": "*" + } + }, + "node_modules/aws4": { + "version": "1.11.0", + "license": "MIT" + }, + "node_modules/axe-core": { + "version": "4.4.3", + "dev": true, + "license": "MPL-2.0", + "engines": { + "node": ">=4" + } + }, + "node_modules/axobject-query": { + "version": "2.2.0", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/babel-code-frame": { + "version": "6.26.0", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^1.1.3", + "esutils": "^2.0.2", + "js-tokens": "^3.0.2" + } + }, + "node_modules/babel-code-frame/node_modules/ansi-regex": { + "version": "2.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/babel-code-frame/node_modules/ansi-styles": { + "version": "2.2.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/babel-code-frame/node_modules/chalk": { + "version": "1.1.3", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/babel-code-frame/node_modules/js-tokens": { + "version": "3.0.2", + "dev": true, + "license": "MIT" + }, + "node_modules/babel-code-frame/node_modules/strip-ansi": { + "version": "3.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/babel-code-frame/node_modules/supports-color": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2": { + "version": "0.3.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.17.7", + "@babel/helper-define-polyfill-provider": "^0.3.3", + "semver": "^6.1.1" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": { + "version": "6.3.0", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.6.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.3.3", + "core-js-compat": "^3.25.1" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/babel-plugin-polyfill-regenerator": { + "version": "0.4.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.3.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/babel-polyfill": { + "version": "6.26.0", + "dev": true, + "license": "MIT", + "dependencies": { + "babel-runtime": "^6.26.0", + "core-js": "^2.5.0", + "regenerator-runtime": "^0.10.5" + } + }, + "node_modules/babel-polyfill/node_modules/regenerator-runtime": { + "version": "0.10.5", + "dev": true, + "license": "MIT" + }, + "node_modules/babel-runtime": { + "version": "6.26.0", + "dev": true, + "license": "MIT", + "dependencies": { + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" + } + }, + "node_modules/babel-runtime/node_modules/regenerator-runtime": { + "version": "0.11.1", + "dev": true, + "license": "MIT" + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "license": "MIT" + }, + "node_modules/base32.js": { + "version": "0.1.0", + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/base64id": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": "^4.5.0 || >= 5.9" + } + }, + "node_modules/bcrypt-pbkdf": { + "version": "1.0.2", + "license": "BSD-3-Clause", + "dependencies": { + "tweetnacl": "^0.14.3" + } + }, + "node_modules/bech32": { + "version": "1.1.4", + "license": "MIT" + }, + "node_modules/benchmark": { + "version": "2.1.4", + "dev": true, + "license": "MIT", + "dependencies": { + "lodash": "^4.17.4", + "platform": "^1.3.3" + } + }, + "node_modules/big.js": { + "version": "5.2.2", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/bigint-crypto-utils": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/bigint-crypto-utils/-/bigint-crypto-utils-3.2.2.tgz", + "integrity": "sha512-U1RbE3aX9ayCUVcIPHuPDPKcK3SFOXf93J1UK/iHlJuQB7bhagPIX06/CLpLEsDThJ7KA4Dhrnzynl+d2weTiw==", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/bignumber.js": { + "version": "9.1.0", + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/bindings": { + "version": "1.5.0", + "license": "MIT", + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/blakejs": { + "version": "1.2.1", + "license": "MIT" + }, + "node_modules/bn.js": { + "version": "5.2.1", + "license": "MIT" + }, + "node_modules/body-parser": { + "version": "1.20.1", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.1", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/body-parser/node_modules/debug": { + "version": "2.6.9", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/body-parser/node_modules/ms": { + "version": "2.0.0", + "license": "MIT" + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/brorand": { + "version": "1.1.0", + "license": "MIT" + }, + "node_modules/browser-level": { + "version": "1.0.1", + "license": "MIT", + "dependencies": { + "abstract-level": "^1.0.2", + "catering": "^2.1.1", + "module-error": "^1.0.2", + "run-parallel-limit": "^1.1.0" + } + }, + "node_modules/browser-pack": { + "version": "6.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "combine-source-map": "~0.8.0", + "defined": "^1.0.0", + "JSONStream": "^1.0.3", + "safe-buffer": "^5.1.1", + "through2": "^2.0.0", + "umd": "^3.0.0" + }, + "bin": { + "browser-pack": "bin/cmd.js" + } + }, + "node_modules/browser-process-hrtime": { + "version": "0.1.3", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/browser-resolve": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve": "^1.17.0" + } + }, + "node_modules/browserify": { + "version": "16.5.2", + "dev": true, + "license": "MIT", + "dependencies": { + "assert": "^1.4.0", + "browser-pack": "^6.0.1", + "browser-resolve": "^2.0.0", + "browserify-zlib": "~0.2.0", + "buffer": "~5.2.1", + "cached-path-relative": "^1.0.0", + "concat-stream": "^1.6.0", + "console-browserify": "^1.1.0", + "constants-browserify": "~1.0.0", + "crypto-browserify": "^3.0.0", + "defined": "^1.0.0", + "deps-sort": "^2.0.0", + "domain-browser": "^1.2.0", + "duplexer2": "~0.1.2", + "events": "^2.0.0", + "glob": "^7.1.0", + "has": "^1.0.0", + "htmlescape": "^1.1.0", + "https-browserify": "^1.0.0", + "inherits": "~2.0.1", + "insert-module-globals": "^7.0.0", + "JSONStream": "^1.0.3", + "labeled-stream-splicer": "^2.0.0", + "mkdirp-classic": "^0.5.2", + "module-deps": "^6.2.3", + "os-browserify": "~0.3.0", + "parents": "^1.0.1", + "path-browserify": "~0.0.0", + "process": "~0.11.0", + "punycode": "^1.3.2", + "querystring-es3": "~0.2.0", + "read-only-stream": "^2.0.0", + "readable-stream": "^2.0.2", + "resolve": "^1.1.4", + "shasum": "^1.0.0", + "shell-quote": "^1.6.1", + "stream-browserify": "^2.0.0", + "stream-http": "^3.0.0", + "string_decoder": "^1.1.1", + "subarg": "^1.0.0", + "syntax-error": "^1.1.1", + "through2": "^2.0.0", + "timers-browserify": "^1.0.1", + "tty-browserify": "0.0.1", + "url": "~0.11.0", + "util": "~0.10.1", + "vm-browserify": "^1.0.0", + "xtend": "^4.0.0" + }, + "bin": { + "browserify": "bin/cmd.js" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/browserify-aes": { + "version": "1.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/browserify-cipher": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "browserify-aes": "^1.0.4", + "browserify-des": "^1.0.0", + "evp_bytestokey": "^1.0.0" + } + }, + "node_modules/browserify-des": { + "version": "1.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "cipher-base": "^1.0.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/browserify-rsa": { + "version": "4.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "bn.js": "^5.0.0", + "randombytes": "^2.0.1" + } + }, + "node_modules/browserify-sign": { + "version": "4.2.1", + "dev": true, + "license": "ISC", + "dependencies": { + "bn.js": "^5.1.1", + "browserify-rsa": "^4.0.1", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "elliptic": "^6.5.3", + "inherits": "^2.0.4", + "parse-asn1": "^5.1.5", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + } + }, + "node_modules/browserify-sign/node_modules/readable-stream": { + "version": "3.6.0", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/browserify-zlib": { + "version": "0.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "pako": "~1.0.5" + } + }, + "node_modules/browserify/node_modules/buffer": { + "version": "5.2.1", + "dev": true, + "license": "MIT", + "dependencies": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "node_modules/browserify/node_modules/inherits": { + "version": "2.0.3", + "dev": true, + "license": "ISC" + }, + "node_modules/browserify/node_modules/stream-browserify": { + "version": "2.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "~2.0.1", + "readable-stream": "^2.0.2" + } + }, + "node_modules/browserify/node_modules/util": { + "version": "0.10.4", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "2.0.3" + } + }, + "node_modules/browserslist": { + "version": "4.21.4", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + } + ], + "license": "MIT", + "dependencies": { + "caniuse-lite": "^1.0.30001400", + "electron-to-chromium": "^1.4.251", + "node-releases": "^2.0.6", + "update-browserslist-db": "^1.0.9" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/buffer": { + "version": "6.0.3", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "dev": true, + "license": "MIT" + }, + "node_modules/buffer-xor": { + "version": "1.0.3", + "dev": true, + "license": "MIT" + }, + "node_modules/builtin-modules": { + "version": "1.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/builtin-status-codes": { + "version": "3.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/bytes": { + "version": "3.1.2", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/c-kzg": { + "version": "2.0.4", + "license": "MIT", + "dependencies": { + "bindings": "^1.5.0", + "node-addon-api": "^5.0.0" + } + }, + "node_modules/c-kzg/node_modules/node-addon-api": { + "version": "5.1.0", + "license": "MIT" + }, + "node_modules/c8": { + "version": "7.12.0", + "dev": true, + "license": "ISC", + "dependencies": { + "@bcoe/v8-coverage": "^0.2.3", + "@istanbuljs/schema": "^0.1.3", + "find-up": "^5.0.0", + "foreground-child": "^2.0.0", + "istanbul-lib-coverage": "^3.2.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-reports": "^3.1.4", + "rimraf": "^3.0.2", + "test-exclude": "^6.0.0", + "v8-to-istanbul": "^9.0.0", + "yargs": "^16.2.0", + "yargs-parser": "^20.2.9" + }, + "bin": { + "c8": "bin/c8.js" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/cached-path-relative": { + "version": "1.1.0", + "dev": true, + "license": "MIT" + }, + "node_modules/caching-transform": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "hasha": "^5.0.0", + "make-dir": "^3.0.0", + "package-hash": "^4.0.0", + "write-file-atomic": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/caching-transform/node_modules/make-dir": { + "version": "3.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/caching-transform/node_modules/semver": { + "version": "6.3.0", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/call-bind": { + "version": "1.0.2", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/caller-path": { + "version": "0.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^0.2.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/caller-path/node_modules/callsites": { + "version": "0.2.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/camel-case": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "no-case": "^2.2.0", + "upper-case": "^1.1.1" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001423", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/caseless": { + "version": "0.12.0", + "license": "Apache-2.0" + }, + "node_modules/catering": { + "version": "2.1.1", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/chai": { + "version": "4.3.6", + "license": "MIT", + "dependencies": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.2", + "deep-eql": "^3.0.1", + "get-func-name": "^2.0.0", + "loupe": "^2.3.1", + "pathval": "^1.1.1", + "type-detect": "^4.0.5" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/chai-checkmark": { + "version": "1.0.1", + "license": "ISC" + }, + "node_modules/chalk": { + "version": "4.1.2", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/check-error": { + "version": "1.0.2", + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/chokidar": { + "version": "3.5.3", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/chrome-trace-event": { + "version": "1.0.3", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0" + } + }, + "node_modules/cids": { + "version": "1.1.9", + "license": "MIT", + "dependencies": { + "multibase": "^4.0.1", + "multicodec": "^3.0.1", + "multihashes": "^4.0.1", + "uint8arrays": "^3.0.0" + }, + "engines": { + "node": ">=4.0.0", + "npm": ">=3.0.0" + } + }, + "node_modules/cids/node_modules/multicodec": { + "version": "3.2.1", + "license": "MIT", + "dependencies": { + "uint8arrays": "^3.0.0", + "varint": "^6.0.0" + } + }, + "node_modules/cipher-base": { + "version": "1.0.4", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/circular-json": { + "version": "0.3.3", + "dev": true, + "license": "MIT" + }, + "node_modules/class-is": { + "version": "1.1.0", + "license": "MIT" + }, + "node_modules/classic-level": { + "version": "1.2.0", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "abstract-level": "^1.0.2", + "catering": "^2.1.0", + "module-error": "^1.0.1", + "napi-macros": "~2.0.0", + "node-gyp-build": "^4.3.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/clean-stack": { + "version": "2.2.0", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/cli-cursor": { + "version": "3.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "restore-cursor": "^3.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-truncate": { + "version": "3.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "slice-ansi": "^5.0.0", + "string-width": "^5.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-width": { + "version": "2.2.1", + "dev": true, + "license": "ISC" + }, + "node_modules/cliui": { + "version": "7.0.4", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/cliui/node_modules/emoji-regex": { + "version": "8.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/cliui/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/string-width": { + "version": "4.2.3", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/clone": { + "version": "1.0.4", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/clone-deep": { + "version": "4.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/co": { + "version": "4.6.0", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" + } + }, + "node_modules/code-point-at": { + "version": "1.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/color": { + "version": "3.2.1", + "license": "MIT", + "dependencies": { + "color-convert": "^1.9.3", + "color-string": "^1.6.0" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "license": "MIT" + }, + "node_modules/color-string": { + "version": "1.9.1", + "license": "MIT", + "dependencies": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, + "node_modules/color/node_modules/color-convert": { + "version": "1.9.3", + "license": "MIT", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color/node_modules/color-name": { + "version": "1.1.3", + "license": "MIT" + }, + "node_modules/colorette": { + "version": "2.0.19", + "dev": true, + "license": "MIT" + }, + "node_modules/colors": { + "version": "0.6.2", + "dev": true, + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/colorspace": { + "version": "1.1.4", + "license": "MIT", + "dependencies": { + "color": "^3.1.3", + "text-hex": "1.0.x" + } + }, + "node_modules/combine-source-map": { + "version": "0.8.0", + "dev": true, + "license": "MIT", + "dependencies": { + "convert-source-map": "~1.1.0", + "inline-source-map": "~0.6.0", + "lodash.memoize": "~3.0.3", + "source-map": "~0.5.3" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/command-exists": { + "version": "1.2.9", + "dev": true, + "license": "MIT" + }, + "node_modules/commander": { + "version": "2.1.0", + "dev": true, + "engines": { + "node": ">= 0.6.x" + } + }, + "node_modules/commondir": { + "version": "1.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/component-emitter": { + "version": "1.3.0", + "dev": true, + "license": "MIT" + }, + "node_modules/concat-map": { + "version": "0.0.1", + "license": "MIT" + }, + "node_modules/concat-stream": { + "version": "1.6.2", + "dev": true, + "engines": [ + "node >= 0.8" + ], + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/connect": { + "version": "3.7.0", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "finalhandler": "1.1.2", + "parseurl": "~1.3.3", + "utils-merge": "1.0.1" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/connect/node_modules/debug": { + "version": "2.6.9", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/connect/node_modules/ms": { + "version": "2.0.0", + "license": "MIT" + }, + "node_modules/console-browserify": { + "version": "1.2.0", + "dev": true + }, + "node_modules/constants-browserify": { + "version": "1.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/contains-path": { + "version": "0.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/content-type": { + "version": "1.0.4", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/convert-source-map": { + "version": "1.1.3", + "dev": true, + "license": "MIT" + }, + "node_modules/cookie": { + "version": "0.4.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookiejar": { + "version": "2.1.3", + "dev": true, + "license": "MIT" + }, + "node_modules/core-js": { + "version": "2.6.12", + "dev": true, + "hasInstallScript": true, + "license": "MIT" + }, + "node_modules/core-js-compat": { + "version": "3.25.5", + "dev": true, + "license": "MIT", + "dependencies": { + "browserslist": "^4.21.4" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-js-pure": { + "version": "3.25.5", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "dev": true, + "license": "MIT" + }, + "node_modules/cors": { + "version": "2.8.5", + "license": "MIT", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/crc-32": { + "version": "1.2.2", + "license": "Apache-2.0", + "bin": { + "crc32": "bin/crc32.njs" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/create-ecdh": { + "version": "4.0.4", + "dev": true, + "license": "MIT", + "dependencies": { + "bn.js": "^4.1.0", + "elliptic": "^6.5.3" + } + }, + "node_modules/create-ecdh/node_modules/bn.js": { + "version": "4.12.0", + "dev": true, + "license": "MIT" + }, + "node_modules/create-hash": { + "version": "1.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "node_modules/create-hmac": { + "version": "1.1.7", + "dev": true, + "license": "MIT", + "dependencies": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "node_modules/create-require": { + "version": "1.1.1", + "dev": true, + "license": "MIT" + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/cross-spawn/node_modules/which": { + "version": "2.0.2", + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/crypto-browserify": { + "version": "3.12.0", + "dev": true, + "license": "MIT", + "dependencies": { + "browserify-cipher": "^1.0.0", + "browserify-sign": "^4.0.0", + "create-ecdh": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.0", + "diffie-hellman": "^5.0.0", + "inherits": "^2.0.1", + "pbkdf2": "^3.0.3", + "public-encrypt": "^4.0.0", + "randombytes": "^2.0.0", + "randomfill": "^1.0.3" + }, + "engines": { + "node": "*" + } + }, + "node_modules/custom-event": { + "version": "1.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/d": { + "version": "1.0.1", + "dev": true, + "license": "ISC", + "dependencies": { + "es5-ext": "^0.10.50", + "type": "^1.0.1" + } + }, + "node_modules/d3-array": { + "version": "2.12.1", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "internmap": "^1.0.0" + } + }, + "node_modules/d3-color": { + "version": "2.0.0", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/d3-dispatch": { + "version": "1.0.6", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/d3-drag": { + "version": "1.2.5", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "d3-dispatch": "1", + "d3-selection": "1" + } + }, + "node_modules/d3-ease": { + "version": "1.0.7", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/d3-fg": { + "version": "6.14.0", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "d3-array": "^2.2.0", + "d3-dispatch": "^1.0.5", + "d3-ease": "^1.0.5", + "d3-hierarchy": "^1.1.8", + "d3-scale": "^3.0.0", + "d3-selection": "^1.4.0", + "d3-zoom": "^1.7.3", + "escape-string-regexp": "^1.0.5", + "hsl-to-rgb-for-reals": "^1.1.0" + } + }, + "node_modules/d3-format": { + "version": "2.0.0", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/d3-hierarchy": { + "version": "1.1.9", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/d3-interpolate": { + "version": "2.0.1", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "d3-color": "1 - 2" + } + }, + "node_modules/d3-scale": { + "version": "3.3.0", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "d3-array": "^2.3.0", + "d3-format": "1 - 2", + "d3-interpolate": "1.2.0 - 2", + "d3-time": "^2.1.1", + "d3-time-format": "2 - 3" + } + }, + "node_modules/d3-selection": { + "version": "1.4.2", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/d3-time": { + "version": "2.1.1", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "d3-array": "2" + } + }, + "node_modules/d3-time-format": { + "version": "3.0.0", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "d3-time": "1 - 2" + } + }, + "node_modules/d3-timer": { + "version": "1.0.10", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/d3-transition": { + "version": "1.3.2", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "d3-color": "1", + "d3-dispatch": "1", + "d3-ease": "1", + "d3-interpolate": "1", + "d3-selection": "^1.1.0", + "d3-timer": "1" + } + }, + "node_modules/d3-transition/node_modules/d3-color": { + "version": "1.4.1", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/d3-transition/node_modules/d3-interpolate": { + "version": "1.4.0", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "d3-color": "1" + } + }, + "node_modules/d3-zoom": { + "version": "1.8.3", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "d3-dispatch": "1", + "d3-drag": "1", + "d3-interpolate": "1", + "d3-selection": "1", + "d3-transition": "1" + } + }, + "node_modules/d3-zoom/node_modules/d3-color": { + "version": "1.4.1", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/d3-zoom/node_modules/d3-interpolate": { + "version": "1.4.0", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "d3-color": "1" + } + }, + "node_modules/damerau-levenshtein": { + "version": "1.0.8", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/dash-ast": { + "version": "1.0.0", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/dashdash": { + "version": "1.14.1", + "license": "MIT", + "dependencies": { + "assert-plus": "^1.0.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/date-format": { + "version": "4.0.14", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/debounce": { + "version": "1.2.1", + "dev": true, + "license": "MIT" + }, + "node_modules/debug": { + "version": "4.3.4", + "license": "MIT", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/debug-log": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/debug/node_modules/ms": { + "version": "2.1.2", + "license": "MIT" + }, + "node_modules/decamelize": { + "version": "1.2.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/deep-eql": { + "version": "3.0.1", + "license": "MIT", + "dependencies": { + "type-detect": "^4.0.0" + }, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/deep-equal": { + "version": "2.0.5", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.0", + "es-get-iterator": "^1.1.1", + "get-intrinsic": "^1.0.1", + "is-arguments": "^1.0.4", + "is-date-object": "^1.0.2", + "is-regex": "^1.1.1", + "isarray": "^2.0.5", + "object-is": "^1.1.4", + "object-keys": "^1.1.1", + "object.assign": "^4.1.2", + "regexp.prototype.flags": "^1.3.0", + "side-channel": "^1.0.3", + "which-boxed-primitive": "^1.0.1", + "which-collection": "^1.0.1", + "which-typed-array": "^1.1.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/deep-equal/node_modules/isarray": { + "version": "2.0.5", + "dev": true, + "license": "MIT" + }, + "node_modules/deep-is": { + "version": "0.1.4", + "dev": true, + "license": "MIT" + }, + "node_modules/default-gateway": { + "version": "6.0.3", + "license": "BSD-2-Clause", + "dependencies": { + "execa": "^5.0.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/default-require-extensions": { + "version": "3.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "strip-bom": "^4.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/defaults": { + "version": "1.0.4", + "dev": true, + "license": "MIT", + "dependencies": { + "clone": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deferred-leveldown": { + "version": "7.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "abstract-leveldown": "^7.2.0", + "inherits": "^2.0.3" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/define-properties": { + "version": "1.1.4", + "license": "MIT", + "dependencies": { + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/defined": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/deglob": { + "version": "2.1.1", + "dev": true, + "license": "ISC", + "dependencies": { + "find-root": "^1.0.0", + "glob": "^7.0.5", + "ignore": "^3.0.9", + "pkg-config": "^1.1.0", + "run-parallel": "^1.1.2", + "uniq": "^1.0.1" + } + }, + "node_modules/deglob/node_modules/ignore": { + "version": "3.3.10", + "dev": true, + "license": "MIT" + }, + "node_modules/delay": { + "version": "5.0.0", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/deps-sort": { + "version": "2.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "JSONStream": "^1.0.3", + "shasum-object": "^1.0.0", + "subarg": "^1.0.0", + "through2": "^2.0.0" + }, + "bin": { + "deps-sort": "bin/cmd.js" + } + }, + "node_modules/des.js": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "license": "MIT", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/detect-indent": { + "version": "6.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/detect-newline": { + "version": "3.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/detect-node": { + "version": "2.1.0", + "license": "MIT" + }, + "node_modules/detective": { + "version": "5.2.1", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn-node": "^1.8.2", + "defined": "^1.0.0", + "minimist": "^1.2.6" + }, + "bin": { + "detective": "bin/detective.js" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/dezalgo": { + "version": "1.0.3", + "dev": true, + "license": "ISC", + "dependencies": { + "asap": "^2.0.0", + "wrappy": "1" + } + }, + "node_modules/di": { + "version": "0.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/diff": { + "version": "4.0.2", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/diffie-hellman": { + "version": "5.0.3", + "dev": true, + "license": "MIT", + "dependencies": { + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" + } + }, + "node_modules/diffie-hellman/node_modules/bn.js": { + "version": "4.12.0", + "dev": true, + "license": "MIT" + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/dirty-chai": { + "version": "2.0.1", + "license": "MIT", + "peerDependencies": { + "chai": ">=2.2.1 <5" + } + }, + "node_modules/dns-over-http-resolver": { + "version": "1.2.3", + "license": "MIT", + "dependencies": { + "debug": "^4.3.1", + "native-fetch": "^3.0.0", + "receptacle": "^1.3.2" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/dom-serialize": { + "version": "2.2.1", + "dev": true, + "license": "MIT", + "dependencies": { + "custom-event": "~1.0.0", + "ent": "~2.2.0", + "extend": "^3.0.0", + "void-elements": "^2.0.0" + } + }, + "node_modules/domain-browser": { + "version": "1.2.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4", + "npm": ">=1.2" + } + }, + "node_modules/dotignore": { + "version": "0.1.2", + "dev": true, + "license": "MIT", + "dependencies": { + "minimatch": "^3.0.4" + }, + "bin": { + "ignored": "bin/ignored" + } + }, + "node_modules/duplexer2": { + "version": "0.1.4", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "readable-stream": "^2.0.2" + } + }, + "node_modules/duplexify": { + "version": "3.7.1", + "dev": true, + "license": "MIT", + "dependencies": { + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "dev": true, + "license": "MIT" + }, + "node_modules/ecc-jsbn": { + "version": "0.1.2", + "license": "MIT", + "dependencies": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "node_modules/ecc-jsbn/node_modules/jsbn": { + "version": "0.1.1", + "license": "MIT" + }, + "node_modules/ee-first": { + "version": "1.1.1", + "license": "MIT" + }, + "node_modules/electron-fetch": { + "version": "1.9.1", + "license": "MIT", + "dependencies": { + "encoding": "^0.1.13" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.4.284", + "dev": true, + "license": "ISC" + }, + "node_modules/elliptic": { + "version": "6.5.4", + "license": "MIT", + "dependencies": { + "bn.js": "^4.11.9", + "brorand": "^1.1.0", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/elliptic/node_modules/bn.js": { + "version": "4.12.0", + "license": "MIT" + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "dev": true, + "license": "MIT" + }, + "node_modules/emojis-list": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/enabled": { + "version": "2.0.0", + "license": "MIT" + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/encoding": { + "version": "0.1.13", + "license": "MIT", + "dependencies": { + "iconv-lite": "^0.6.2" + } + }, + "node_modules/encoding-down": { + "version": "7.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "abstract-leveldown": "^7.2.0", + "inherits": "^2.0.3", + "level-codec": "^10.0.0", + "level-errors": "^3.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/encoding/node_modules/iconv-lite": { + "version": "0.6.3", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "dev": true, + "license": "MIT", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/engine.io": { + "version": "6.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/cookie": "^0.4.1", + "@types/cors": "^2.8.12", + "@types/node": ">=10.0.0", + "accepts": "~1.3.4", + "base64id": "2.0.0", + "cookie": "~0.4.1", + "cors": "~2.8.5", + "debug": "~4.3.1", + "engine.io-parser": "~5.0.3", + "ws": "~8.2.3" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/engine.io-parser": { + "version": "5.0.4", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/engine.io/node_modules/ws": { + "version": "8.2.3", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/enhanced-resolve": { + "version": "5.10.0", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/ent": { + "version": "2.2.0", + "dev": true, + "license": "MIT" + }, + "node_modules/env-string": { + "version": "1.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/envinfo": { + "version": "7.8.1", + "dev": true, + "license": "MIT", + "bin": { + "envinfo": "dist/cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/err-code": { + "version": "2.0.3", + "license": "MIT" + }, + "node_modules/error-ex": { + "version": "1.3.2", + "dev": true, + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-abstract": { + "version": "1.20.4", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "function.prototype.name": "^1.1.5", + "get-intrinsic": "^1.1.3", + "get-symbol-description": "^1.0.0", + "has": "^1.0.3", + "has-property-descriptors": "^1.0.0", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.3", + "is-callable": "^1.2.7", + "is-negative-zero": "^2.0.2", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "is-string": "^1.0.7", + "is-weakref": "^1.0.2", + "object-inspect": "^1.12.2", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.4.3", + "safe-regex-test": "^1.0.0", + "string.prototype.trimend": "^1.0.5", + "string.prototype.trimstart": "^1.0.5", + "unbox-primitive": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-get-iterator": { + "version": "1.1.2", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.0", + "has-symbols": "^1.0.1", + "is-arguments": "^1.1.0", + "is-map": "^2.0.2", + "is-set": "^2.0.2", + "is-string": "^1.0.5", + "isarray": "^2.0.5" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-get-iterator/node_modules/isarray": { + "version": "2.0.5", + "dev": true, + "license": "MIT" + }, + "node_modules/es-module-lexer": { + "version": "0.9.3", + "dev": true, + "license": "MIT" + }, + "node_modules/es-shim-unscopables": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "has": "^1.0.3" + } + }, + "node_modules/es-to-primitive": { + "version": "1.2.1", + "license": "MIT", + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es5-ext": { + "version": "0.10.62", + "dev": true, + "hasInstallScript": true, + "license": "ISC", + "dependencies": { + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.3", + "next-tick": "^1.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/es6-error": { + "version": "4.1.1", + "dev": true, + "license": "MIT" + }, + "node_modules/es6-iterator": { + "version": "2.0.3", + "dev": true, + "license": "MIT", + "dependencies": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, + "node_modules/es6-map": { + "version": "0.1.5", + "dev": true, + "license": "MIT", + "dependencies": { + "d": "1", + "es5-ext": "~0.10.14", + "es6-iterator": "~2.0.1", + "es6-set": "~0.1.5", + "es6-symbol": "~3.1.1", + "event-emitter": "~0.3.5" + } + }, + "node_modules/es6-object-assign": { + "version": "1.1.0", + "dev": true, + "license": "MIT" + }, + "node_modules/es6-promise": { + "version": "4.2.8", + "license": "MIT" + }, + "node_modules/es6-promisify": { + "version": "5.0.0", + "license": "MIT", + "dependencies": { + "es6-promise": "^4.0.3" + } + }, + "node_modules/es6-set": { + "version": "0.1.6", + "dev": true, + "license": "ISC", + "dependencies": { + "d": "^1.0.1", + "es5-ext": "^0.10.62", + "es6-iterator": "~2.0.3", + "es6-symbol": "^3.1.3", + "event-emitter": "^0.3.5", + "type": "^2.7.2" + }, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/es6-set/node_modules/type": { + "version": "2.7.2", + "dev": true, + "license": "ISC" + }, + "node_modules/es6-symbol": { + "version": "3.1.3", + "dev": true, + "license": "ISC", + "dependencies": { + "d": "^1.0.1", + "ext": "^1.1.2" + } + }, + "node_modules/es6-weak-map": { + "version": "2.0.3", + "dev": true, + "license": "ISC", + "dependencies": { + "d": "1", + "es5-ext": "^0.10.46", + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.1" + } + }, + "node_modules/escalade": { + "version": "3.1.1", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "license": "MIT" + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/escope": { + "version": "3.6.0", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "es6-map": "^0.1.3", + "es6-weak-map": "^2.0.1", + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/eslint": { + "version": "8.22.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint/eslintrc": "^1.3.0", + "@humanwhocodes/config-array": "^0.10.4", + "@humanwhocodes/gitignore-to-minimatch": "^1.0.2", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.1.1", + "eslint-utils": "^3.0.0", + "eslint-visitor-keys": "^3.3.0", + "espree": "^9.3.3", + "esquery": "^1.4.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^6.0.1", + "globals": "^13.15.0", + "globby": "^11.1.0", + "grapheme-splitter": "^1.0.4", + "ignore": "^5.2.0", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "regexpp": "^3.2.0", + "strip-ansi": "^6.0.1", + "strip-json-comments": "^3.1.0", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-config-prettier": { + "version": "8.5.0", + "dev": true, + "license": "MIT", + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-config-standard": { + "version": "10.2.1", + "dev": true, + "license": "MIT", + "peerDependencies": { + "eslint": ">=3.19.0", + "eslint-plugin-import": ">=2.2.0", + "eslint-plugin-node": ">=4.2.2", + "eslint-plugin-promise": ">=3.5.0", + "eslint-plugin-standard": ">=3.0.0" + } + }, + "node_modules/eslint-config-typestrict": { + "version": "1.0.5", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@typescript-eslint/eslint-plugin": "^5", + "eslint-plugin-sonarjs": "*" + } + }, + "node_modules/eslint-formatter-codeframe": { + "version": "7.32.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "7.12.11", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/eslint-import-resolver-node": { + "version": "0.3.6", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^3.2.7", + "resolve": "^1.20.0" + } + }, + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "3.2.7", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-import-resolver-node/node_modules/ms": { + "version": "2.1.3", + "dev": true, + "license": "MIT" + }, + "node_modules/eslint-module-utils": { + "version": "2.7.4", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^3.2.7" + }, + "engines": { + "node": ">=4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } + } + }, + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "3.2.7", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-module-utils/node_modules/ms": { + "version": "2.1.3", + "dev": true, + "license": "MIT" + }, + "node_modules/eslint-plugin-escompat": { + "version": "3.3.4", + "dev": true, + "license": "MIT", + "dependencies": { + "browserslist": "^4.21.0" + }, + "peerDependencies": { + "eslint": ">=5.14.1" + } + }, + "node_modules/eslint-plugin-eslint-comments": { + "version": "3.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^1.0.5", + "ignore": "^5.0.5" + }, + "engines": { + "node": ">=6.5.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=4.19.1" + } + }, + "node_modules/eslint-plugin-ethereumjs": { + "resolved": "eslint", + "link": true + }, + "node_modules/eslint-plugin-filenames": { + "version": "1.3.2", + "dev": true, + "license": "MIT", + "dependencies": { + "lodash.camelcase": "4.3.0", + "lodash.kebabcase": "4.1.1", + "lodash.snakecase": "4.1.1", + "lodash.upperfirst": "4.3.1" + }, + "peerDependencies": { + "eslint": "*" + } + }, + "node_modules/eslint-plugin-github": { + "version": "4.3.7", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/eslint-plugin": "^5.1.0", + "@typescript-eslint/parser": "^5.1.0", + "eslint-config-prettier": ">=8.0.0", + "eslint-plugin-escompat": "^3.1.0", + "eslint-plugin-eslint-comments": "^3.2.0", + "eslint-plugin-filenames": "^1.3.2", + "eslint-plugin-i18n-text": "^1.0.1", + "eslint-plugin-import": "^2.25.2", + "eslint-plugin-jsx-a11y": "^6.6.0", + "eslint-plugin-no-only-tests": "^2.6.0", + "eslint-plugin-prettier": "^4.0.0", + "eslint-rule-documentation": ">=1.0.0", + "jsx-ast-utils": "^3.3.2", + "prettier": "^2.2.1", + "svg-element-attributes": "^1.3.1" + }, + "bin": { + "eslint-ignore-errors": "bin/eslint-ignore-errors.js" + }, + "peerDependencies": { + "eslint": "^8.0.1" + } + }, + "node_modules/eslint-plugin-i18n-text": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "peerDependencies": { + "eslint": ">=5.0.0" + } + }, + "node_modules/eslint-plugin-implicit-dependencies": { + "version": "1.1.1", + "dev": true, + "license": "MIT", + "dependencies": { + "builtin-modules": "^1.1.1", + "findup": "^0.1.5" + } + }, + "node_modules/eslint-plugin-import": { + "version": "2.26.0", + "dev": true, + "license": "MIT", + "dependencies": { + "array-includes": "^3.1.4", + "array.prototype.flat": "^1.2.5", + "debug": "^2.6.9", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.6", + "eslint-module-utils": "^2.7.3", + "has": "^1.0.3", + "is-core-module": "^2.8.1", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.values": "^1.1.5", + "resolve": "^1.22.0", + "tsconfig-paths": "^3.14.1" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" + } + }, + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "2.6.9", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/eslint-plugin-import/node_modules/doctrine": { + "version": "2.1.0", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-plugin-import/node_modules/ms": { + "version": "2.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/eslint-plugin-jsx-a11y": { + "version": "6.6.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.9", + "aria-query": "^4.2.2", + "array-includes": "^3.1.5", + "ast-types-flow": "^0.0.7", + "axe-core": "^4.4.3", + "axobject-query": "^2.2.0", + "damerau-levenshtein": "^1.0.8", + "emoji-regex": "^9.2.2", + "has": "^1.0.3", + "jsx-ast-utils": "^3.3.2", + "language-tags": "^1.0.5", + "minimatch": "^3.1.2", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=4.0" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" + } + }, + "node_modules/eslint-plugin-jsx-a11y/node_modules/semver": { + "version": "6.3.0", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-plugin-no-only-tests": { + "version": "2.6.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/eslint-plugin-node": { + "version": "4.2.3", + "dev": true, + "license": "MIT", + "dependencies": { + "ignore": "^3.0.11", + "minimatch": "^3.0.2", + "object-assign": "^4.0.1", + "resolve": "^1.1.7", + "semver": "5.3.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": ">=3.1.0" + } + }, + "node_modules/eslint-plugin-node/node_modules/ignore": { + "version": "3.3.10", + "dev": true, + "license": "MIT" + }, + "node_modules/eslint-plugin-node/node_modules/semver": { + "version": "5.3.0", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/eslint-plugin-prettier": { + "version": "4.2.1", + "dev": true, + "license": "MIT", + "dependencies": { + "prettier-linter-helpers": "^1.0.0" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "eslint": ">=7.28.0", + "prettier": ">=2.0.0" + }, + "peerDependenciesMeta": { + "eslint-config-prettier": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-promise": { + "version": "3.5.0", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=4" + } + }, + "node_modules/eslint-plugin-simple-import-sort": { + "version": "7.0.0", + "dev": true, + "license": "MIT", + "peerDependencies": { + "eslint": ">=5.0.0" + } + }, + "node_modules/eslint-plugin-sonarjs": { + "version": "0.14.0", + "dev": true, + "license": "LGPL-3.0", + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "eslint": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/eslint-plugin-standard": { + "version": "3.0.1", + "dev": true, + "license": "MIT", + "peerDependencies": { + "eslint": ">=3.19.0" + } + }, + "node_modules/eslint-rule-documentation": { + "version": "1.0.23", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/eslint-scope": { + "version": "5.1.1", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/eslint-utils": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^2.0.0" + }, + "engines": { + "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=5" + } + }, + "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "2.1.0", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.3.0", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/eslint/node_modules/escape-string-regexp": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/eslint-scope": { + "version": "7.1.1", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/eslint/node_modules/estraverse": { + "version": "5.3.0", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/espree": { + "version": "9.4.0", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.8.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "dev": true, + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esquery": { + "version": "1.4.0", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esquery/node_modules/estraverse": { + "version": "5.3.0", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse/node_modules/estraverse": { + "version": "5.3.0", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "4.3.0", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estree-is-member-expression": { + "version": "1.0.0", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/esutils": { + "version": "2.0.3", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ethereum-cryptography": { + "version": "2.0.0", + "license": "MIT", + "dependencies": { + "@noble/curves": "1.0.0", + "@noble/hashes": "1.3.0", + "@scure/bip32": "1.3.0", + "@scure/bip39": "1.2.0" + } + }, + "node_modules/ethers": { + "version": "5.7.2", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/abi": "5.7.0", + "@ethersproject/abstract-provider": "5.7.0", + "@ethersproject/abstract-signer": "5.7.0", + "@ethersproject/address": "5.7.0", + "@ethersproject/base64": "5.7.0", + "@ethersproject/basex": "5.7.0", + "@ethersproject/bignumber": "5.7.0", + "@ethersproject/bytes": "5.7.0", + "@ethersproject/constants": "5.7.0", + "@ethersproject/contracts": "5.7.0", + "@ethersproject/hash": "5.7.0", + "@ethersproject/hdnode": "5.7.0", + "@ethersproject/json-wallets": "5.7.0", + "@ethersproject/keccak256": "5.7.0", + "@ethersproject/logger": "5.7.0", + "@ethersproject/networks": "5.7.1", + "@ethersproject/pbkdf2": "5.7.0", + "@ethersproject/properties": "5.7.0", + "@ethersproject/providers": "5.7.2", + "@ethersproject/random": "5.7.0", + "@ethersproject/rlp": "5.7.0", + "@ethersproject/sha2": "5.7.0", + "@ethersproject/signing-key": "5.7.0", + "@ethersproject/solidity": "5.7.0", + "@ethersproject/strings": "5.7.0", + "@ethersproject/transactions": "5.7.0", + "@ethersproject/units": "5.7.0", + "@ethersproject/wallet": "5.7.0", + "@ethersproject/web": "5.7.1", + "@ethersproject/wordlists": "5.7.0" + } + }, + "node_modules/event-emitter": { + "version": "0.3.5", + "dev": true, + "license": "MIT", + "dependencies": { + "d": "1", + "es5-ext": "~0.10.14" + } + }, + "node_modules/event-iterator": { + "version": "2.0.0", + "license": "MIT" + }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/eventemitter3": { + "version": "4.0.7", + "license": "MIT" + }, + "node_modules/events": { + "version": "2.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4.x" + } + }, + "node_modules/evp_bytestokey": { + "version": "1.0.3", + "dev": true, + "license": "MIT", + "dependencies": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/execa": { + "version": "5.1.1", + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/execspawn": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "util-extend": "^1.0.1" + } + }, + "node_modules/exit-hook": { + "version": "1.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ext": { + "version": "1.7.0", + "dev": true, + "license": "ISC", + "dependencies": { + "type": "^2.7.2" + } + }, + "node_modules/ext/node_modules/type": { + "version": "2.7.2", + "dev": true, + "license": "ISC" + }, + "node_modules/extend": { + "version": "3.0.2", + "license": "MIT" + }, + "node_modules/extsprintf": { + "version": "1.3.0", + "engines": [ + "node >=0.6.0" + ], + "license": "MIT" + }, + "node_modules/eyes": { + "version": "0.1.8", + "engines": { + "node": "> 0.1.90" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "license": "MIT" + }, + "node_modules/fast-diff": { + "version": "1.2.0", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/fast-fifo": { + "version": "1.1.0", + "license": "MIT" + }, + "node_modules/fast-glob": { + "version": "3.2.12", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-redact": { + "version": "2.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/fast-safe-stringify": { + "version": "2.1.1", + "dev": true, + "license": "MIT" + }, + "node_modules/fastest-levenshtein": { + "version": "1.0.16", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4.9.1" + } + }, + "node_modules/fastq": { + "version": "1.13.0", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fecha": { + "version": "4.2.3", + "license": "MIT" + }, + "node_modules/figures": { + "version": "1.7.0", + "dev": true, + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^1.0.5", + "object-assign": "^4.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/file-replace-loader": { + "version": "1.4.0", + "dev": true, + "license": "MIT", + "dependencies": { + "loader-utils": "^2.0.0", + "schema-utils": "^2.7.1" + } + }, + "node_modules/file-stream-rotator": { + "version": "0.6.1", + "license": "MIT", + "dependencies": { + "moment": "^2.29.1" + } + }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "license": "MIT" + }, + "node_modules/fill-range": { + "version": "7.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.1.2", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "license": "MIT" + }, + "node_modules/finalhandler/node_modules/on-finished": { + "version": "2.3.0", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/find-cache-dir": { + "version": "3.3.2", + "dev": true, + "license": "MIT", + "dependencies": { + "commondir": "^1.0.1", + "make-dir": "^3.0.2", + "pkg-dir": "^4.1.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/avajs/find-cache-dir?sponsor=1" + } + }, + "node_modules/find-cache-dir/node_modules/make-dir": { + "version": "3.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/find-cache-dir/node_modules/semver": { + "version": "6.3.0", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/find-root": { + "version": "1.1.0", + "dev": true, + "license": "MIT" + }, + "node_modules/find-up": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/findup": { + "version": "0.1.5", + "dev": true, + "dependencies": { + "colors": "~0.6.0-1", + "commander": "~2.1.0" + }, + "bin": { + "findup": "bin/findup.js" + }, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/flat-cache": { + "version": "3.0.4", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatstr": { + "version": "1.0.12", + "dev": true, + "license": "MIT" + }, + "node_modules/flatted": { + "version": "3.2.7", + "dev": true, + "license": "ISC" + }, + "node_modules/fn.name": { + "version": "1.1.0", + "license": "MIT" + }, + "node_modules/follow-redirects": { + "version": "1.15.2", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/for-each": { + "version": "0.3.3", + "license": "MIT", + "dependencies": { + "is-callable": "^1.1.3" + } + }, + "node_modules/foreground-child": { + "version": "2.0.0", + "dev": true, + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/forever-agent": { + "version": "0.6.1", + "license": "Apache-2.0", + "engines": { + "node": "*" + } + }, + "node_modules/form-data": { + "version": "2.3.3", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 0.12" + } + }, + "node_modules/formidable": { + "version": "2.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "dezalgo": "1.0.3", + "hexoid": "1.0.0", + "once": "1.4.0", + "qs": "6.9.3" + }, + "funding": { + "url": "https://ko-fi.com/tunnckoCore/commissions" + } + }, + "node_modules/formidable/node_modules/qs": { + "version": "6.9.3", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/fromentries": { + "version": "1.3.2", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/fs-extra": { + "version": "10.1.0", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "dev": true, + "license": "ISC" + }, + "node_modules/function-bind": { + "version": "1.1.1", + "license": "MIT" + }, + "node_modules/function.prototype.name": { + "version": "1.1.5", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.0", + "functions-have-names": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functional-red-black-tree": { + "version": "1.0.1", + "license": "MIT" + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/generate-function": { + "version": "2.3.1", + "dev": true, + "license": "MIT", + "dependencies": { + "is-property": "^1.0.2" + } + }, + "node_modules/generate-object-property": { + "version": "1.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "is-property": "^1.0.0" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-assigned-identifiers": { + "version": "1.2.0", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-func-name": { + "version": "2.0.0", + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.1.3", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-iterator": { + "version": "1.0.2", + "license": "MIT" + }, + "node_modules/get-package-type": { + "version": "0.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/get-stdin": { + "version": "5.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-symbol-description": { + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/getpass": { + "version": "0.1.7", + "license": "MIT", + "dependencies": { + "assert-plus": "^1.0.0" + } + }, + "node_modules/git-hooks-list": { + "version": "1.0.3", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/fisker/git-hooks-list?sponsor=1" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/glob-to-regexp": { + "version": "0.4.1", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/globals": { + "version": "13.17.0", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.10", + "license": "ISC" + }, + "node_modules/grapheme-splitter": { + "version": "1.0.4", + "dev": true, + "license": "MIT" + }, + "node_modules/handlebars": { + "version": "4.7.7", + "dev": true, + "license": "MIT", + "dependencies": { + "minimist": "^1.2.5", + "neo-async": "^2.6.0", + "source-map": "^0.6.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "handlebars": "bin/handlebars" + }, + "engines": { + "node": ">=0.4.7" + }, + "optionalDependencies": { + "uglify-js": "^3.1.4" + } + }, + "node_modules/handlebars/node_modules/source-map": { + "version": "0.6.1", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/har-schema": { + "version": "2.0.0", + "license": "ISC", + "engines": { + "node": ">=4" + } + }, + "node_modules/har-validator": { + "version": "5.1.5", + "license": "MIT", + "dependencies": { + "ajv": "^6.12.3", + "har-schema": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/has": { + "version": "1.0.3", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-ansi": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-ansi/node_modules/ansi-regex": { + "version": "2.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-bigints": { + "version": "1.0.2", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-dynamic-import": { + "version": "2.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-unicode": { + "version": "2.0.1", + "dev": true, + "license": "ISC" + }, + "node_modules/hash-base": { + "version": "3.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/hash-base/node_modules/readable-stream": { + "version": "3.6.0", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/hash.js": { + "version": "1.1.7", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "node_modules/hasha": { + "version": "5.2.2", + "dev": true, + "license": "MIT", + "dependencies": { + "is-stream": "^2.0.0", + "type-fest": "^0.8.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/hasha/node_modules/type-fest": { + "version": "0.8.1", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=8" + } + }, + "node_modules/hashlru": { + "version": "2.3.0", + "license": "MIT" + }, + "node_modules/heap": { + "version": "0.2.7", + "license": "MIT" + }, + "node_modules/hexoid": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/hmac-drbg": { + "version": "1.0.1", + "license": "MIT", + "dependencies": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/hsl-to-rgb-for-reals": { + "version": "1.1.1", + "dev": true, + "license": "ISC" + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "dev": true, + "license": "MIT" + }, + "node_modules/htmlescape": { + "version": "1.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/http-errors": { + "version": "2.0.0", + "license": "MIT", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-errors/node_modules/statuses": { + "version": "2.0.1", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-proxy": { + "version": "1.18.1", + "dev": true, + "license": "MIT", + "dependencies": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/http-signature": { + "version": "1.2.0", + "license": "MIT", + "dependencies": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + }, + "engines": { + "node": ">=0.8", + "npm": ">=1.3.7" + } + }, + "node_modules/https-browserify": { + "version": "1.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/human-signals": { + "version": "2.1.0", + "license": "Apache-2.0", + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/hyperscript-attribute-to-property": { + "version": "1.0.2", + "dev": true, + "license": "MIT" + }, + "node_modules/hyperx": { + "version": "2.5.4", + "dev": true, + "license": "BSD", + "dependencies": { + "hyperscript-attribute-to-property": "^1.0.0" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/ignore": { + "version": "5.2.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-local": { + "version": "3.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "dev": true, + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "license": "ISC" + }, + "node_modules/inline-source-map": { + "version": "0.6.2", + "dev": true, + "license": "MIT", + "dependencies": { + "source-map": "~0.5.3" + } + }, + "node_modules/inquirer": { + "version": "0.12.0", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-escapes": "^1.1.0", + "ansi-regex": "^2.0.0", + "chalk": "^1.0.0", + "cli-cursor": "^1.0.1", + "cli-width": "^2.0.0", + "figures": "^1.3.5", + "lodash": "^4.3.0", + "readline2": "^1.0.1", + "run-async": "^0.1.0", + "rx-lite": "^3.1.2", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.0", + "through": "^2.3.6" + } + }, + "node_modules/inquirer/node_modules/ansi-escapes": { + "version": "1.4.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/inquirer/node_modules/ansi-regex": { + "version": "2.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/inquirer/node_modules/ansi-styles": { + "version": "2.2.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/inquirer/node_modules/chalk": { + "version": "1.1.3", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/inquirer/node_modules/cli-cursor": { + "version": "1.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "restore-cursor": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/inquirer/node_modules/is-fullwidth-code-point": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "number-is-nan": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/inquirer/node_modules/onetime": { + "version": "1.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/inquirer/node_modules/restore-cursor": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "exit-hook": "^1.0.0", + "onetime": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/inquirer/node_modules/string-width": { + "version": "1.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/inquirer/node_modules/strip-ansi": { + "version": "3.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/inquirer/node_modules/supports-color": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/insert-module-globals": { + "version": "7.2.1", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn-node": "^1.5.2", + "combine-source-map": "^0.8.0", + "concat-stream": "^1.6.1", + "is-buffer": "^1.1.0", + "JSONStream": "^1.0.3", + "path-is-absolute": "^1.0.1", + "process": "~0.11.0", + "through2": "^2.0.0", + "undeclared-identifiers": "^1.1.2", + "xtend": "^4.0.0" + }, + "bin": { + "insert-module-globals": "bin/cmd.js" + } + }, + "node_modules/insert-module-globals/node_modules/is-buffer": { + "version": "1.1.6", + "dev": true, + "license": "MIT" + }, + "node_modules/interface-datastore": { + "version": "3.0.6", + "license": "MIT", + "dependencies": { + "err-code": "^3.0.1", + "ipfs-utils": "^6.0.0", + "iso-random-stream": "^2.0.0", + "it-all": "^1.0.2", + "it-drain": "^1.0.1", + "nanoid": "^3.0.2" + } + }, + "node_modules/interface-datastore/node_modules/err-code": { + "version": "3.0.1", + "license": "MIT" + }, + "node_modules/internal-slot": { + "version": "1.0.3", + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.1.0", + "has": "^1.0.3", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/internmap": { + "version": "1.0.1", + "dev": true, + "license": "ISC" + }, + "node_modules/interpret": { + "version": "2.2.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/ip-address": { + "version": "6.4.0", + "license": "MIT", + "dependencies": { + "jsbn": "1.1.0", + "lodash.find": "4.6.0", + "lodash.max": "4.0.1", + "lodash.merge": "4.6.2", + "lodash.padstart": "4.6.1", + "lodash.repeat": "4.1.0", + "sprintf-js": "1.1.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/ip-regex": { + "version": "4.3.0", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ipaddr.js": { + "version": "2.0.1", + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/ipfs-utils": { + "version": "6.0.8", + "license": "MIT", + "dependencies": { + "abort-controller": "^3.0.0", + "any-signal": "^2.1.0", + "buffer": "^6.0.1", + "electron-fetch": "^1.7.2", + "err-code": "^3.0.1", + "is-electron": "^2.2.0", + "iso-url": "^1.0.0", + "it-glob": "~0.0.11", + "it-to-stream": "^1.0.0", + "merge-options": "^3.0.4", + "nanoid": "^3.1.20", + "native-abort-controller": "^1.0.3", + "native-fetch": "^3.0.0", + "node-fetch": "^2.6.1", + "stream-to-it": "^0.2.2" + } + }, + "node_modules/ipfs-utils/node_modules/err-code": { + "version": "3.0.1", + "license": "MIT" + }, + "node_modules/is-arguments": { + "version": "1.1.1", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "dev": true, + "license": "MIT" + }, + "node_modules/is-bigint": { + "version": "1.0.4", + "license": "MIT", + "dependencies": { + "has-bigints": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-boolean-attribute": { + "version": "0.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/is-boolean-object": { + "version": "1.1.2", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-buffer": { + "version": "2.0.5", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.11.0", + "dev": true, + "license": "MIT", + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.0.5", + "license": "MIT", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-docker": { + "version": "2.2.1", + "dev": true, + "license": "MIT", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-electron": { + "version": "2.2.1", + "license": "MIT" + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fn": { + "version": "1.0.0", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-generator-function": { + "version": "1.0.10", + "license": "MIT", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-ip": { + "version": "3.1.0", + "license": "MIT", + "dependencies": { + "ip-regex": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-loopback-addr": { + "version": "1.0.1", + "license": "MIT" + }, + "node_modules/is-map": { + "version": "2.0.2", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-my-ip-valid": { + "version": "1.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/is-my-json-valid": { + "version": "2.20.6", + "dev": true, + "license": "MIT", + "dependencies": { + "generate-function": "^2.0.0", + "generate-object-property": "^1.1.0", + "is-my-ip-valid": "^1.0.0", + "jsonpointer": "^5.0.0", + "xtend": "^4.0.0" + } + }, + "node_modules/is-nan": { + "version": "1.3.2", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.2", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-number-object": { + "version": "1.0.7", + "license": "MIT", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-plain-obj": { + "version": "2.1.0", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-object": { + "version": "2.0.4", + "dev": true, + "license": "MIT", + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-property": { + "version": "1.0.2", + "dev": true, + "license": "MIT" + }, + "node_modules/is-regex": { + "version": "1.1.4", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-regexp": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-resolvable": { + "version": "1.1.0", + "dev": true, + "license": "ISC" + }, + "node_modules/is-set": { + "version": "2.0.2", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.2", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-string": { + "version": "1.0.7", + "license": "MIT", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.0.4", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.9", + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "es-abstract": "^1.20.0", + "for-each": "^0.3.3", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "license": "MIT" + }, + "node_modules/is-weakmap": { + "version": "2.0.1", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakref": { + "version": "1.0.2", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakset": { + "version": "2.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-windows": { + "version": "1.0.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-wsl": { + "version": "2.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/isbinaryfile": { + "version": "4.0.10", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/gjtorikian/" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "license": "ISC" + }, + "node_modules/iso-random-stream": { + "version": "2.0.2", + "license": "MIT", + "dependencies": { + "events": "^3.3.0", + "readable-stream": "^3.4.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/iso-random-stream/node_modules/events": { + "version": "3.3.0", + "license": "MIT", + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/iso-random-stream/node_modules/readable-stream": { + "version": "3.6.0", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/iso-url": { + "version": "1.2.1", + "license": "MIT", + "engines": { + "node": ">=12" + } + }, + "node_modules/isobject": { + "version": "3.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isomorphic-ws": { + "version": "4.0.1", + "license": "MIT", + "peerDependencies": { + "ws": "*" + } + }, + "node_modules/isstream": { + "version": "0.1.2", + "license": "MIT" + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.0", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-hook": { + "version": "3.0.0", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "append-transform": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument": { + "version": "4.0.3", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/core": "^7.7.5", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.0.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument/node_modules/semver": { + "version": "6.3.0", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/istanbul-lib-processinfo": { + "version": "2.0.3", + "dev": true, + "license": "ISC", + "dependencies": { + "archy": "^1.0.0", + "cross-spawn": "^7.0.3", + "istanbul-lib-coverage": "^3.2.0", + "p-map": "^3.0.0", + "rimraf": "^3.0.0", + "uuid": "^8.3.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-processinfo/node_modules/p-map": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.0", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^3.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-report/node_modules/make-dir": { + "version": "3.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/istanbul-lib-report/node_modules/semver": { + "version": "6.3.0", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/istanbul-lib-source-maps": { + "version": "4.0.1", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-source-maps/node_modules/source-map": { + "version": "0.6.1", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/istanbul-reports": { + "version": "3.1.5", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/it-all": { + "version": "1.0.6", + "license": "ISC" + }, + "node_modules/it-buffer": { + "version": "0.1.3", + "license": "MPL-2.0", + "dependencies": { + "bl": "^5.0.0", + "buffer": "^6.0.3" + } + }, + "node_modules/it-buffer/node_modules/bl": { + "version": "5.1.0", + "license": "MIT", + "dependencies": { + "buffer": "^6.0.3", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/it-buffer/node_modules/readable-stream": { + "version": "3.6.0", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/it-drain": { + "version": "1.0.5", + "license": "ISC" + }, + "node_modules/it-filter": { + "version": "1.0.3", + "license": "ISC" + }, + "node_modules/it-first": { + "version": "1.0.7", + "license": "ISC" + }, + "node_modules/it-glob": { + "version": "0.0.14", + "license": "ISC", + "dependencies": { + "@types/minimatch": "^3.0.4", + "minimatch": "^3.0.4" + } + }, + "node_modules/it-goodbye": { + "version": "2.0.2", + "license": "MIT", + "dependencies": { + "buffer": "^5.6.0" + } + }, + "node_modules/it-goodbye/node_modules/buffer": { + "version": "5.7.1", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/it-handshake": { + "version": "2.0.0", + "license": "MIT", + "dependencies": { + "it-pushable": "^1.4.0", + "it-reader": "^3.0.0", + "p-defer": "^3.0.0" + } + }, + "node_modules/it-length-prefixed": { + "version": "5.0.3", + "license": "MIT", + "dependencies": { + "bl": "^5.0.0", + "buffer": "^6.0.3", + "varint": "^6.0.0" + } + }, + "node_modules/it-length-prefixed/node_modules/bl": { + "version": "5.1.0", + "license": "MIT", + "dependencies": { + "buffer": "^6.0.3", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/it-length-prefixed/node_modules/readable-stream": { + "version": "3.6.0", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/it-map": { + "version": "1.0.6", + "license": "ISC" + }, + "node_modules/it-merge": { + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "it-pushable": "^1.4.0" + } + }, + "node_modules/it-pair": { + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "get-iterator": "^1.0.2" + } + }, + "node_modules/it-pb-rpc": { + "version": "0.1.13", + "license": "MPL-2.0", + "dependencies": { + "is-buffer": "^2.0.5", + "it-handshake": "^2.0.0", + "it-length-prefixed": "^5.0.2" + } + }, + "node_modules/it-pipe": { + "version": "1.1.0", + "license": "MIT" + }, + "node_modules/it-protocol-buffers": { + "version": "0.2.1", + "license": "MIT", + "dependencies": { + "it-buffer": "^0.1.1", + "it-length-prefixed": "^3.0.0" + } + }, + "node_modules/it-protocol-buffers/node_modules/bl": { + "version": "4.1.0", + "license": "MIT", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/it-protocol-buffers/node_modules/buffer": { + "version": "5.7.1", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/it-protocol-buffers/node_modules/it-length-prefixed": { + "version": "3.1.0", + "license": "MIT", + "dependencies": { + "@types/bl": "^2.1.0", + "bl": "^4.0.2", + "buffer": "^5.5.0", + "varint": "^5.0.0" + } + }, + "node_modules/it-protocol-buffers/node_modules/readable-stream": { + "version": "3.6.0", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/it-protocol-buffers/node_modules/varint": { + "version": "5.0.2", + "license": "MIT" + }, + "node_modules/it-pushable": { + "version": "1.4.2", + "license": "MIT", + "dependencies": { + "fast-fifo": "^1.0.0" + } + }, + "node_modules/it-reader": { + "version": "3.0.0", + "license": "MIT", + "dependencies": { + "bl": "^5.0.0" + } + }, + "node_modules/it-reader/node_modules/bl": { + "version": "5.1.0", + "license": "MIT", + "dependencies": { + "buffer": "^6.0.3", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/it-reader/node_modules/readable-stream": { + "version": "3.6.0", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/it-take": { + "version": "1.0.0", + "license": "ISC" + }, + "node_modules/it-to-stream": { + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "buffer": "^6.0.3", + "fast-fifo": "^1.0.0", + "get-iterator": "^1.0.2", + "p-defer": "^3.0.0", + "p-fifo": "^1.0.0", + "readable-stream": "^3.6.0" + } + }, + "node_modules/it-to-stream/node_modules/readable-stream": { + "version": "3.6.0", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/it-ws": { + "version": "4.0.0", + "license": "MIT", + "dependencies": { + "buffer": "^6.0.3", + "event-iterator": "^2.0.0", + "iso-url": "^1.1.2", + "ws": "^7.3.1" + } + }, + "node_modules/jayson": { + "version": "4.0.0", + "license": "MIT", + "dependencies": { + "@types/connect": "^3.4.33", + "@types/node": "^12.12.54", + "@types/ws": "^7.4.4", + "commander": "^2.20.3", + "delay": "^5.0.0", + "es6-promisify": "^5.0.0", + "eyes": "^0.1.8", + "isomorphic-ws": "^4.0.1", + "json-stringify-safe": "^5.0.1", + "JSONStream": "^1.3.5", + "uuid": "^8.3.2", + "ws": "^7.4.5" + }, + "bin": { + "jayson": "bin/jayson.js" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jayson/node_modules/@types/node": { + "version": "12.20.55", + "license": "MIT" + }, + "node_modules/jayson/node_modules/commander": { + "version": "2.20.3", + "license": "MIT" + }, + "node_modules/jest-worker": { + "version": "27.5.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/js-sdsl": { + "version": "4.1.5", + "license": "MIT" + }, + "node_modules/js-sha3": { + "version": "0.8.0", + "license": "MIT" + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsbn": { + "version": "1.1.0", + "license": "MIT" + }, + "node_modules/jsesc": { + "version": "2.5.2", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/json-parse-better-errors": { + "version": "1.0.2", + "dev": true, + "license": "MIT" + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema": { + "version": "0.4.0", + "license": "(AFL-2.1 OR BSD-3-Clause)" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "license": "MIT" + }, + "node_modules/json-stable-stringify": { + "version": "0.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "jsonify": "~0.0.0" + } + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "license": "ISC" + }, + "node_modules/json5": { + "version": "2.2.1", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonc-parser": { + "version": "3.2.0", + "dev": true, + "license": "MIT" + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsonify": { + "version": "0.0.1", + "dev": true, + "license": "Public Domain", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/jsonparse": { + "version": "1.3.1", + "engines": [ + "node >= 0.2.0" + ], + "license": "MIT" + }, + "node_modules/jsonpointer": { + "version": "5.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/JSONStream": { + "version": "1.3.5", + "license": "(MIT OR Apache-2.0)", + "dependencies": { + "jsonparse": "^1.2.0", + "through": ">=2.2.7 <3" + }, + "bin": { + "JSONStream": "bin.js" + }, + "engines": { + "node": "*" + } + }, + "node_modules/jsonstream2": { + "version": "1.1.2", + "dev": true, + "license": "MIT", + "dependencies": { + "jsonparse": "0.0.6", + "through2": "^0.6.1", + "type-component": "0.0.1" + }, + "bin": { + "jsonstream": "bin/jsonstream.js" + } + }, + "node_modules/jsonstream2/node_modules/isarray": { + "version": "0.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/jsonstream2/node_modules/jsonparse": { + "version": "0.0.6", + "dev": true, + "engines": [ + "node >= 0.2.0" + ], + "license": "MIT" + }, + "node_modules/jsonstream2/node_modules/readable-stream": { + "version": "1.0.34", + "dev": true, + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "node_modules/jsonstream2/node_modules/string_decoder": { + "version": "0.10.31", + "dev": true, + "license": "MIT" + }, + "node_modules/jsonstream2/node_modules/through2": { + "version": "0.6.5", + "dev": true, + "license": "MIT", + "dependencies": { + "readable-stream": ">=1.0.33-1 <1.1.0-0", + "xtend": ">=4.0.0 <4.1.0-0" + } + }, + "node_modules/jsprim": { + "version": "1.4.2", + "license": "MIT", + "dependencies": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.4.0", + "verror": "1.10.0" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/jsx-ast-utils": { + "version": "3.3.3", + "dev": true, + "license": "MIT", + "dependencies": { + "array-includes": "^3.1.5", + "object.assign": "^4.1.3" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/just-extend": { + "version": "4.2.1", + "license": "MIT" + }, + "node_modules/jwt-simple": { + "version": "0.5.6", + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/k-bucket": { + "version": "5.1.0", + "license": "MIT", + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/karma": { + "version": "6.4.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@colors/colors": "1.5.0", + "body-parser": "^1.19.0", + "braces": "^3.0.2", + "chokidar": "^3.5.1", + "connect": "^3.7.0", + "di": "^0.0.1", + "dom-serialize": "^2.2.1", + "glob": "^7.1.7", + "graceful-fs": "^4.2.6", + "http-proxy": "^1.18.1", + "isbinaryfile": "^4.0.8", + "lodash": "^4.17.21", + "log4js": "^6.4.1", + "mime": "^2.5.2", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.5", + "qjobs": "^1.2.0", + "range-parser": "^1.2.1", + "rimraf": "^3.0.2", + "socket.io": "^4.4.1", + "source-map": "^0.6.1", + "tmp": "^0.2.1", + "ua-parser-js": "^0.7.30", + "yargs": "^16.1.1" + }, + "bin": { + "karma": "bin/karma" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/karma-chrome-launcher": { + "version": "3.1.1", + "dev": true, + "license": "MIT", + "dependencies": { + "which": "^1.2.1" + } + }, + "node_modules/karma-firefox-launcher": { + "version": "2.1.2", + "dev": true, + "license": "MIT", + "dependencies": { + "is-wsl": "^2.2.0", + "which": "^2.0.1" + } + }, + "node_modules/karma-firefox-launcher/node_modules/which": { + "version": "2.0.2", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/karma-tap": { + "version": "4.2.0", + "dev": true, + "license": "ISC", + "dependencies": { + "babel-polyfill": "^6.26.0" + }, + "peerDependencies": { + "karma": ">=1.0.0" + } + }, + "node_modules/karma-typescript": { + "version": "5.5.3", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.1.0", + "acorn-walk": "^8.0.2", + "assert": "^2.0.0", + "async": "^3.0.1", + "browser-resolve": "^2.0.0", + "browserify-zlib": "^0.2.0", + "buffer": "^5.4.3", + "combine-source-map": "^0.8.0", + "console-browserify": "^1.2.0", + "constants-browserify": "^1.0.0", + "convert-source-map": "^1.7.0", + "crypto-browserify": "^3.12.0", + "diff": "^4.0.1", + "domain-browser": "^4.16.0", + "events": "^3.2.0", + "glob": "^7.1.6", + "https-browserify": "^1.0.0", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^4.0.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.0.0", + "json-stringify-safe": "^5.0.1", + "lodash": "^4.17.19", + "log4js": "^6.3.0", + "minimatch": "^3.0.4", + "os-browserify": "^0.3.0", + "pad": "^3.2.0", + "path-browserify": "^1.0.0", + "process": "^0.11.10", + "punycode": "^2.1.1", + "querystring-es3": "^0.2.1", + "readable-stream": "^3.1.1", + "source-map": "^0.7.3", + "stream-browserify": "^3.0.0", + "stream-http": "^3.1.0", + "string_decoder": "^1.3.0", + "timers-browserify": "^2.0.11", + "tmp": "^0.2.1", + "tty-browserify": "^0.0.1", + "url": "^0.11.0", + "util": "^0.12.1", + "vm-browserify": "^1.1.2" + }, + "peerDependencies": { + "karma": "1 || 2 || 3 || 4 || 5 || 6", + "typescript": "1 || 2 || 3 || 4" + } + }, + "node_modules/karma-typescript-es6-transform": { + "version": "5.5.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.11.1", + "@babel/preset-env": "^7.11.0", + "acorn": "^8.1.0", + "acorn-walk": "^8.0.2", + "log4js": "^6.3.0", + "magic-string": "^0.25.7" + } + }, + "node_modules/karma-typescript-es6-transform/node_modules/acorn-walk": { + "version": "8.2.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/karma-typescript/node_modules/acorn-walk": { + "version": "8.2.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/karma-typescript/node_modules/assert": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "es6-object-assign": "^1.1.0", + "is-nan": "^1.2.1", + "object-is": "^1.0.1", + "util": "^0.12.0" + } + }, + "node_modules/karma-typescript/node_modules/buffer": { + "version": "5.7.1", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/karma-typescript/node_modules/convert-source-map": { + "version": "1.9.0", + "dev": true, + "license": "MIT" + }, + "node_modules/karma-typescript/node_modules/domain-browser": { + "version": "4.22.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://bevry.me/fund" + } + }, + "node_modules/karma-typescript/node_modules/events": { + "version": "3.3.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/karma-typescript/node_modules/path-browserify": { + "version": "1.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/karma-typescript/node_modules/punycode": { + "version": "2.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/karma-typescript/node_modules/readable-stream": { + "version": "3.6.0", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/karma-typescript/node_modules/source-map": { + "version": "0.7.4", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">= 8" + } + }, + "node_modules/karma-typescript/node_modules/timers-browserify": { + "version": "2.0.12", + "dev": true, + "license": "MIT", + "dependencies": { + "setimmediate": "^1.0.4" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/karma/node_modules/source-map": { + "version": "0.6.1", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/keypair": { + "version": "1.0.4", + "license": "BSD / GPL" + }, + "node_modules/kind-of": { + "version": "6.0.3", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/kuler": { + "version": "2.0.0", + "license": "MIT" + }, + "node_modules/labeled-stream-splicer": { + "version": "2.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.1", + "stream-splicer": "^2.0.0" + } + }, + "node_modules/language-subtag-registry": { + "version": "0.3.22", + "dev": true, + "license": "CC0-1.0" + }, + "node_modules/language-tags": { + "version": "1.0.5", + "dev": true, + "license": "MIT", + "dependencies": { + "language-subtag-registry": "~0.3.2" + } + }, + "node_modules/level": { + "version": "8.0.0", + "license": "MIT", + "dependencies": { + "browser-level": "^1.0.1", + "classic-level": "^1.2.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/level" + } + }, + "node_modules/level-codec": { + "version": "10.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer": "^6.0.3" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/level-concat-iterator": { + "version": "3.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "catering": "^2.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/level-errors": { + "version": "3.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/level-iterator-stream": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/level-iterator-stream/node_modules/readable-stream": { + "version": "3.6.0", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/level-js": { + "version": "6.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "abstract-leveldown": "^7.2.0", + "buffer": "^6.0.3", + "inherits": "^2.0.3", + "ltgt": "^2.1.2", + "run-parallel-limit": "^1.1.0" + } + }, + "node_modules/level-legacy": { + "name": "level", + "version": "7.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "level-js": "^6.1.0", + "level-packager": "^6.0.1", + "leveldown": "^6.1.0" + }, + "engines": { + "node": ">=10.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/level" + } + }, + "node_modules/level-mem": { + "version": "6.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "level-packager": "^6.0.1", + "memdown": "^6.1.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/level-packager": { + "version": "6.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "encoding-down": "^7.1.0", + "levelup": "^5.1.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/level-supports": { + "version": "4.0.1", + "license": "MIT", + "engines": { + "node": ">=12" + } + }, + "node_modules/level-transcoder": { + "version": "1.0.1", + "license": "MIT", + "dependencies": { + "buffer": "^6.0.3", + "module-error": "^1.0.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/leveldown": { + "version": "6.1.1", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "abstract-leveldown": "^7.2.0", + "napi-macros": "~2.0.0", + "node-gyp-build": "^4.3.0" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/levelup": { + "version": "5.1.1", + "dev": true, + "license": "MIT", + "dependencies": { + "catering": "^2.0.0", + "deferred-leveldown": "^7.0.0", + "level-errors": "^3.0.1", + "level-iterator-stream": "^5.0.0", + "level-supports": "^2.0.1", + "queue-microtask": "^1.2.3" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/levelup/node_modules/level-supports": { + "version": "2.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/libp2p": { + "version": "0.30.13", + "license": "MIT", + "dependencies": { + "@motrix/nat-api": "^0.3.1", + "abort-controller": "^3.0.0", + "aggregate-error": "^3.1.0", + "any-signal": "^2.1.1", + "bignumber.js": "^9.0.1", + "cids": "^1.1.5", + "class-is": "^1.1.0", + "debug": "^4.3.1", + "err-code": "^2.0.0", + "es6-promisify": "^6.1.1", + "events": "^3.2.0", + "hashlru": "^2.3.0", + "interface-datastore": "^3.0.3", + "ipfs-utils": "^6.0.0", + "it-all": "^1.0.4", + "it-buffer": "^0.1.2", + "it-drain": "^1.0.3", + "it-filter": "^1.0.1", + "it-first": "^1.0.4", + "it-handshake": "^1.0.2", + "it-length-prefixed": "^3.1.0", + "it-map": "^1.0.4", + "it-merge": "1.0.0", + "it-pipe": "^1.1.0", + "it-protocol-buffers": "^0.2.0", + "it-take": "1.0.0", + "libp2p-crypto": "^0.19.0", + "libp2p-interfaces": "^0.8.1", + "libp2p-utils": "^0.2.2", + "mafmt": "^8.0.0", + "merge-options": "^3.0.4", + "moving-average": "^1.0.0", + "multiaddr": "^8.1.0", + "multicodec": "^2.1.0", + "multihashing-async": "^2.0.1", + "multistream-select": "^1.0.0", + "mutable-proxy": "^1.0.0", + "node-forge": "^0.10.0", + "p-any": "^3.0.0", + "p-fifo": "^1.0.0", + "p-retry": "^4.2.0", + "p-settle": "^4.0.1", + "peer-id": "^0.14.2", + "private-ip": "^2.0.0", + "protons": "^2.0.0", + "retimer": "^2.0.0", + "sanitize-filename": "^1.6.3", + "set-delayed-interval": "^1.0.0", + "streaming-iterables": "^5.0.2", + "timeout-abort-controller": "^1.1.1", + "uint8arrays": "^2.1.3", + "varint": "^6.0.0", + "xsalsa20": "^1.0.2" + }, + "engines": { + "node": ">=12.0.0", + "npm": ">=6.0.0" + } + }, + "node_modules/libp2p-bootstrap": { + "version": "0.14.0", + "license": "MIT", + "dependencies": { + "debug": "^4.3.1", + "mafmt": "^10.0.0", + "multiaddr": "^10.0.0", + "peer-id": "^0.16.0" + }, + "engines": { + "node": ">=15.0.0" + } + }, + "node_modules/libp2p-bootstrap/node_modules/err-code": { + "version": "3.0.1", + "license": "MIT" + }, + "node_modules/libp2p-bootstrap/node_modules/libp2p-crypto": { + "version": "0.21.2", + "license": "MIT", + "dependencies": { + "@noble/ed25519": "^1.5.1", + "@noble/secp256k1": "^1.3.0", + "err-code": "^3.0.1", + "iso-random-stream": "^2.0.0", + "multiformats": "^9.4.5", + "node-forge": "^1.2.1", + "protobufjs": "^6.11.2", + "uint8arrays": "^3.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/libp2p-bootstrap/node_modules/mafmt": { + "version": "10.0.0", + "license": "MIT", + "dependencies": { + "multiaddr": "^10.0.0" + } + }, + "node_modules/libp2p-bootstrap/node_modules/node-forge": { + "version": "1.3.1", + "license": "(BSD-3-Clause OR GPL-2.0)", + "engines": { + "node": ">= 6.13.0" + } + }, + "node_modules/libp2p-bootstrap/node_modules/peer-id": { + "version": "0.16.0", + "license": "MIT", + "dependencies": { + "class-is": "^1.1.0", + "libp2p-crypto": "^0.21.0", + "multiformats": "^9.4.5", + "protobufjs": "^6.10.2", + "uint8arrays": "^3.0.0" + }, + "engines": { + "node": ">=15.0.0" + } + }, + "node_modules/libp2p-crypto": { + "version": "0.19.7", + "license": "MIT", + "dependencies": { + "err-code": "^3.0.1", + "is-typedarray": "^1.0.0", + "iso-random-stream": "^2.0.0", + "keypair": "^1.0.1", + "multiformats": "^9.4.5", + "node-forge": "^0.10.0", + "pem-jwk": "^2.0.0", + "protobufjs": "^6.11.2", + "secp256k1": "^4.0.0", + "uint8arrays": "^3.0.0", + "ursa-optional": "^0.10.1" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/libp2p-crypto/node_modules/err-code": { + "version": "3.0.1", + "license": "MIT" + }, + "node_modules/libp2p-interfaces": { + "version": "1.3.1", + "license": "MIT", + "dependencies": { + "abort-controller": "^3.0.0", + "abortable-iterator": "^3.0.0", + "debug": "^4.3.1", + "err-code": "^3.0.1", + "it-length-prefixed": "^5.0.2", + "it-pipe": "^1.1.0", + "it-pushable": "^1.4.2", + "libp2p-crypto": "^0.20.0", + "multiaddr": "^10.0.0", + "multiformats": "^9.1.2", + "p-queue": "^6.6.2", + "peer-id": "^0.15.4", + "protobufjs": "^6.10.2", + "uint8arrays": "^3.0.0" + } + }, + "node_modules/libp2p-interfaces/node_modules/err-code": { + "version": "3.0.1", + "license": "MIT" + }, + "node_modules/libp2p-interfaces/node_modules/libp2p-crypto": { + "version": "0.20.0", + "license": "MIT", + "dependencies": { + "err-code": "^3.0.1", + "iso-random-stream": "^2.0.0", + "keypair": "^1.0.4", + "multiformats": "^9.4.5", + "noble-ed25519": "^1.2.6", + "noble-secp256k1": "^1.2.10", + "node-forge": "^0.10.0", + "pem-jwk": "^2.0.0", + "protobufjs": "^6.11.2", + "uint8arrays": "^3.0.0", + "ursa-optional": "^0.10.1" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/libp2p-interfaces/node_modules/peer-id": { + "version": "0.15.4", + "license": "MIT", + "dependencies": { + "class-is": "^1.1.0", + "libp2p-crypto": "^0.20.0", + "minimist": "^1.2.5", + "multiformats": "^9.4.5", + "protobufjs": "^6.10.2", + "uint8arrays": "^3.0.0" + }, + "bin": { + "peer-id": "src/bin.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/libp2p-kad-dht": { + "version": "0.20.6", + "license": "MIT", + "dependencies": { + "abort-controller": "^3.0.0", + "async": "^2.6.2", + "base32.js": "~0.1.0", + "cids": "^1.1.5", + "debug": "^4.3.1", + "err-code": "^2.0.3", + "hashlru": "^2.3.0", + "heap": "~0.2.6", + "interface-datastore": "^3.0.3", + "it-length-prefixed": "^3.1.0", + "it-pipe": "^1.1.0", + "k-bucket": "^5.0.0", + "libp2p-crypto": "^0.19.0", + "libp2p-interfaces": "^0.8.2", + "libp2p-record": "^0.9.0", + "multiaddr": "^8.1.2", + "multihashing-async": "^2.0.1", + "p-filter": "^2.1.0", + "p-map": "^4.0.0", + "p-queue": "^6.6.2", + "p-timeout": "^4.1.0", + "p-times": "^3.0.0", + "peer-id": "^0.14.2", + "promise-to-callback": "^1.0.0", + "protons": "^2.0.0", + "streaming-iterables": "^5.0.4", + "uint8arrays": "^2.0.5", + "varint": "^5.0.0", + "xor-distance": "^2.0.0" + }, + "engines": { + "node": ">=12.0.0", + "npm": ">=6.0.0" + } + }, + "node_modules/libp2p-kad-dht/node_modules/async": { + "version": "2.6.4", + "license": "MIT", + "dependencies": { + "lodash": "^4.17.14" + } + }, + "node_modules/libp2p-kad-dht/node_modules/bl": { + "version": "4.1.0", + "license": "MIT", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/libp2p-kad-dht/node_modules/buffer": { + "version": "5.7.1", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/libp2p-kad-dht/node_modules/delay": { + "version": "4.4.1", + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/libp2p-kad-dht/node_modules/it-length-prefixed": { + "version": "3.1.0", + "license": "MIT", + "dependencies": { + "@types/bl": "^2.1.0", + "bl": "^4.0.2", + "buffer": "^5.5.0", + "varint": "^5.0.0" + } + }, + "node_modules/libp2p-kad-dht/node_modules/libp2p-interfaces": { + "version": "0.8.4", + "license": "MIT", + "dependencies": { + "@types/bl": "^2.1.0", + "abort-controller": "^3.0.0", + "abortable-iterator": "^3.0.0", + "chai": "^4.2.0", + "chai-checkmark": "^1.0.1", + "debug": "^4.3.1", + "delay": "^4.4.0", + "detect-node": "^2.0.4", + "dirty-chai": "^2.0.1", + "err-code": "^2.0.3", + "it-goodbye": "^2.0.2", + "it-length-prefixed": "^3.1.0", + "it-pair": "^1.0.0", + "it-pipe": "^1.1.0", + "it-pushable": "^1.4.0", + "libp2p-crypto": "^0.19.0", + "libp2p-tcp": "^0.15.0", + "multiaddr": "^8.1.2", + "multibase": "^3.1.1", + "multihashes": "^3.1.1", + "p-defer": "^3.0.0", + "p-limit": "^3.1.0", + "p-wait-for": "^3.2.0", + "peer-id": "^0.14.2", + "protons": "^2.0.0", + "sinon": "^9.2.4", + "streaming-iterables": "^5.0.4", + "uint8arrays": "^2.0.5" + } + }, + "node_modules/libp2p-kad-dht/node_modules/multiaddr": { + "version": "8.1.2", + "license": "MIT", + "dependencies": { + "cids": "^1.0.0", + "class-is": "^1.1.0", + "dns-over-http-resolver": "^1.0.0", + "err-code": "^2.0.3", + "is-ip": "^3.1.0", + "multibase": "^3.0.0", + "uint8arrays": "^1.1.0", + "varint": "^5.0.0" + } + }, + "node_modules/libp2p-kad-dht/node_modules/multiaddr/node_modules/uint8arrays": { + "version": "1.1.0", + "license": "MIT", + "dependencies": { + "multibase": "^3.0.0", + "web-encoding": "^1.0.2" + } + }, + "node_modules/libp2p-kad-dht/node_modules/multibase": { + "version": "3.1.2", + "license": "MIT", + "dependencies": { + "@multiformats/base-x": "^4.0.1", + "web-encoding": "^1.0.6" + }, + "engines": { + "node": ">=10.0.0", + "npm": ">=6.0.0" + } + }, + "node_modules/libp2p-kad-dht/node_modules/multihashes": { + "version": "3.1.2", + "license": "MIT", + "dependencies": { + "multibase": "^3.1.0", + "uint8arrays": "^2.0.5", + "varint": "^6.0.0" + }, + "engines": { + "node": ">=10.0.0", + "npm": ">=6.0.0" + } + }, + "node_modules/libp2p-kad-dht/node_modules/multihashes/node_modules/varint": { + "version": "6.0.0", + "license": "MIT" + }, + "node_modules/libp2p-kad-dht/node_modules/readable-stream": { + "version": "3.6.0", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/libp2p-kad-dht/node_modules/uint8arrays": { + "version": "2.1.10", + "license": "MIT", + "dependencies": { + "multiformats": "^9.4.2" + } + }, + "node_modules/libp2p-kad-dht/node_modules/varint": { + "version": "5.0.2", + "license": "MIT" + }, + "node_modules/libp2p-mplex": { + "version": "0.10.7", + "license": "MIT", + "dependencies": { + "abortable-iterator": "^3.0.2", + "bl": "^5.0.0", + "debug": "^4.3.1", + "err-code": "^3.0.1", + "it-pipe": "^1.1.0", + "it-pushable": "^1.4.1", + "varint": "^6.0.0" + } + }, + "node_modules/libp2p-mplex/node_modules/bl": { + "version": "5.1.0", + "license": "MIT", + "dependencies": { + "buffer": "^6.0.3", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/libp2p-mplex/node_modules/err-code": { + "version": "3.0.1", + "license": "MIT" + }, + "node_modules/libp2p-mplex/node_modules/readable-stream": { + "version": "3.6.0", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/libp2p-record": { + "version": "0.9.0", + "license": "MIT", + "dependencies": { + "err-code": "^2.0.0", + "multihashes": "^3.0.1", + "multihashing-async": "^2.0.1", + "protons": "^2.0.0", + "uint8arrays": "^1.1.0" + }, + "engines": { + "node": ">=6.0.0", + "npm": ">=3.0.0" + } + }, + "node_modules/libp2p-record/node_modules/multibase": { + "version": "3.1.2", + "license": "MIT", + "dependencies": { + "@multiformats/base-x": "^4.0.1", + "web-encoding": "^1.0.6" + }, + "engines": { + "node": ">=10.0.0", + "npm": ">=6.0.0" + } + }, + "node_modules/libp2p-record/node_modules/multihashes": { + "version": "3.1.2", + "license": "MIT", + "dependencies": { + "multibase": "^3.1.0", + "uint8arrays": "^2.0.5", + "varint": "^6.0.0" + }, + "engines": { + "node": ">=10.0.0", + "npm": ">=6.0.0" + } + }, + "node_modules/libp2p-record/node_modules/multihashes/node_modules/uint8arrays": { + "version": "2.1.10", + "license": "MIT", + "dependencies": { + "multiformats": "^9.4.2" + } + }, + "node_modules/libp2p-record/node_modules/uint8arrays": { + "version": "1.1.0", + "license": "MIT", + "dependencies": { + "multibase": "^3.0.0", + "web-encoding": "^1.0.2" + } + }, + "node_modules/libp2p-tcp": { + "version": "0.15.4", + "license": "MIT", + "dependencies": { + "abortable-iterator": "^3.0.0", + "class-is": "^1.1.0", + "debug": "^4.3.1", + "err-code": "^3.0.1", + "libp2p-utils": "^0.3.0", + "mafmt": "^9.0.0", + "multiaddr": "^9.0.1", + "stream-to-it": "^0.2.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/libp2p-tcp/node_modules/err-code": { + "version": "3.0.1", + "license": "MIT" + }, + "node_modules/libp2p-tcp/node_modules/ip-address": { + "version": "7.1.0", + "license": "MIT", + "dependencies": { + "jsbn": "1.1.0", + "sprintf-js": "1.1.2" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/libp2p-tcp/node_modules/libp2p-utils": { + "version": "0.3.1", + "license": "MIT", + "dependencies": { + "abortable-iterator": "^3.0.0", + "debug": "^4.3.0", + "err-code": "^3.0.1", + "ip-address": "^7.1.0", + "is-loopback-addr": "^1.0.0", + "multiaddr": "^9.0.1", + "private-ip": "^2.1.1" + } + }, + "node_modules/libp2p-tcp/node_modules/mafmt": { + "version": "9.0.0", + "license": "MIT", + "dependencies": { + "multiaddr": "^9.0.1" + } + }, + "node_modules/libp2p-tcp/node_modules/multiaddr": { + "version": "9.0.2", + "license": "MIT", + "dependencies": { + "cids": "^1.0.0", + "dns-over-http-resolver": "^1.0.0", + "err-code": "^3.0.1", + "is-ip": "^3.1.0", + "multibase": "^4.0.2", + "uint8arrays": "^2.1.3", + "varint": "^6.0.0" + } + }, + "node_modules/libp2p-tcp/node_modules/uint8arrays": { + "version": "2.1.10", + "license": "MIT", + "dependencies": { + "multiformats": "^9.4.2" + } + }, + "node_modules/libp2p-utils": { + "version": "0.2.3", + "license": "MIT", + "dependencies": { + "abortable-iterator": "^3.0.0", + "debug": "^4.2.0", + "err-code": "^2.0.3", + "ip-address": "^6.1.0", + "is-loopback-addr": "^1.0.0", + "multiaddr": "^8.0.0", + "private-ip": "^2.1.1" + } + }, + "node_modules/libp2p-utils/node_modules/multiaddr": { + "version": "8.1.2", + "license": "MIT", + "dependencies": { + "cids": "^1.0.0", + "class-is": "^1.1.0", + "dns-over-http-resolver": "^1.0.0", + "err-code": "^2.0.3", + "is-ip": "^3.1.0", + "multibase": "^3.0.0", + "uint8arrays": "^1.1.0", + "varint": "^5.0.0" + } + }, + "node_modules/libp2p-utils/node_modules/multibase": { + "version": "3.1.2", + "license": "MIT", + "dependencies": { + "@multiformats/base-x": "^4.0.1", + "web-encoding": "^1.0.6" + }, + "engines": { + "node": ">=10.0.0", + "npm": ">=6.0.0" + } + }, + "node_modules/libp2p-utils/node_modules/uint8arrays": { + "version": "1.1.0", + "license": "MIT", + "dependencies": { + "multibase": "^3.0.0", + "web-encoding": "^1.0.2" + } + }, + "node_modules/libp2p-utils/node_modules/varint": { + "version": "5.0.2", + "license": "MIT" + }, + "node_modules/libp2p-websockets": { + "version": "0.15.9", + "license": "MIT", + "dependencies": { + "abortable-iterator": "^3.0.0", + "class-is": "^1.1.0", + "debug": "^4.3.1", + "err-code": "^3.0.1", + "ipfs-utils": "^8.1.2", + "it-ws": "^4.0.0", + "libp2p-utils": "^0.3.0", + "mafmt": "^9.0.0", + "multiaddr": "^9.0.1", + "multiaddr-to-uri": "^7.0.0", + "p-defer": "^3.0.0", + "p-timeout": "^4.1.0" + } + }, + "node_modules/libp2p-websockets/node_modules/err-code": { + "version": "3.0.1", + "license": "MIT" + }, + "node_modules/libp2p-websockets/node_modules/ip-address": { + "version": "7.1.0", + "license": "MIT", + "dependencies": { + "jsbn": "1.1.0", + "sprintf-js": "1.1.2" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/libp2p-websockets/node_modules/ipfs-utils": { + "version": "8.1.6", + "license": "MIT", + "dependencies": { + "abort-controller": "^3.0.0", + "any-signal": "^2.1.0", + "buffer": "^6.0.1", + "electron-fetch": "^1.7.2", + "err-code": "^3.0.1", + "is-electron": "^2.2.0", + "iso-url": "^1.1.5", + "it-glob": "~0.0.11", + "it-to-stream": "^1.0.0", + "merge-options": "^3.0.4", + "nanoid": "^3.1.20", + "native-abort-controller": "^1.0.3", + "native-fetch": "^3.0.0", + "node-fetch": "https://registry.npmjs.org/@achingbrain/node-fetch/-/node-fetch-2.6.7.tgz", + "react-native-fetch-api": "^2.0.0", + "stream-to-it": "^0.2.2" + } + }, + "node_modules/libp2p-websockets/node_modules/libp2p-utils": { + "version": "0.3.1", + "license": "MIT", + "dependencies": { + "abortable-iterator": "^3.0.0", + "debug": "^4.3.0", + "err-code": "^3.0.1", + "ip-address": "^7.1.0", + "is-loopback-addr": "^1.0.0", + "multiaddr": "^9.0.1", + "private-ip": "^2.1.1" + } + }, + "node_modules/libp2p-websockets/node_modules/mafmt": { + "version": "9.0.0", + "license": "MIT", + "dependencies": { + "multiaddr": "^9.0.1" + } + }, + "node_modules/libp2p-websockets/node_modules/multiaddr": { + "version": "9.0.2", + "license": "MIT", + "dependencies": { + "cids": "^1.0.0", + "dns-over-http-resolver": "^1.0.0", + "err-code": "^3.0.1", + "is-ip": "^3.1.0", + "multibase": "^4.0.2", + "uint8arrays": "^2.1.3", + "varint": "^6.0.0" + } + }, + "node_modules/libp2p-websockets/node_modules/node-fetch": { + "name": "@achingbrain/node-fetch", + "version": "2.6.7", + "license": "MIT", + "engines": { + "node": "4.x || >=6.0.0" + } + }, + "node_modules/libp2p-websockets/node_modules/uint8arrays": { + "version": "2.1.10", + "license": "MIT", + "dependencies": { + "multiformats": "^9.4.2" + } + }, + "node_modules/libp2p/node_modules/bl": { + "version": "4.1.0", + "license": "MIT", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/libp2p/node_modules/buffer": { + "version": "5.7.1", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/libp2p/node_modules/delay": { + "version": "4.4.1", + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/libp2p/node_modules/es6-promisify": { + "version": "6.1.1", + "license": "MIT" + }, + "node_modules/libp2p/node_modules/events": { + "version": "3.3.0", + "license": "MIT", + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/libp2p/node_modules/it-handshake": { + "version": "1.0.2", + "license": "MIT", + "dependencies": { + "it-pushable": "^1.4.0", + "it-reader": "^2.0.0", + "p-defer": "^3.0.0" + } + }, + "node_modules/libp2p/node_modules/it-length-prefixed": { + "version": "3.1.0", + "license": "MIT", + "dependencies": { + "@types/bl": "^2.1.0", + "bl": "^4.0.2", + "buffer": "^5.5.0", + "varint": "^5.0.0" + } + }, + "node_modules/libp2p/node_modules/it-length-prefixed/node_modules/varint": { + "version": "5.0.2", + "license": "MIT" + }, + "node_modules/libp2p/node_modules/it-reader": { + "version": "2.1.0", + "license": "MIT", + "dependencies": { + "bl": "^4.0.0" + } + }, + "node_modules/libp2p/node_modules/libp2p-interfaces": { + "version": "0.8.4", + "license": "MIT", + "dependencies": { + "@types/bl": "^2.1.0", + "abort-controller": "^3.0.0", + "abortable-iterator": "^3.0.0", + "chai": "^4.2.0", + "chai-checkmark": "^1.0.1", + "debug": "^4.3.1", + "delay": "^4.4.0", + "detect-node": "^2.0.4", + "dirty-chai": "^2.0.1", + "err-code": "^2.0.3", + "it-goodbye": "^2.0.2", + "it-length-prefixed": "^3.1.0", + "it-pair": "^1.0.0", + "it-pipe": "^1.1.0", + "it-pushable": "^1.4.0", + "libp2p-crypto": "^0.19.0", + "libp2p-tcp": "^0.15.0", + "multiaddr": "^8.1.2", + "multibase": "^3.1.1", + "multihashes": "^3.1.1", + "p-defer": "^3.0.0", + "p-limit": "^3.1.0", + "p-wait-for": "^3.2.0", + "peer-id": "^0.14.2", + "protons": "^2.0.0", + "sinon": "^9.2.4", + "streaming-iterables": "^5.0.4", + "uint8arrays": "^2.0.5" + } + }, + "node_modules/libp2p/node_modules/multiaddr": { + "version": "8.1.2", + "license": "MIT", + "dependencies": { + "cids": "^1.0.0", + "class-is": "^1.1.0", + "dns-over-http-resolver": "^1.0.0", + "err-code": "^2.0.3", + "is-ip": "^3.1.0", + "multibase": "^3.0.0", + "uint8arrays": "^1.1.0", + "varint": "^5.0.0" + } + }, + "node_modules/libp2p/node_modules/multiaddr/node_modules/uint8arrays": { + "version": "1.1.0", + "license": "MIT", + "dependencies": { + "multibase": "^3.0.0", + "web-encoding": "^1.0.2" + } + }, + "node_modules/libp2p/node_modules/multiaddr/node_modules/varint": { + "version": "5.0.2", + "license": "MIT" + }, + "node_modules/libp2p/node_modules/multibase": { + "version": "3.1.2", + "license": "MIT", + "dependencies": { + "@multiformats/base-x": "^4.0.1", + "web-encoding": "^1.0.6" + }, + "engines": { + "node": ">=10.0.0", + "npm": ">=6.0.0" + } + }, + "node_modules/libp2p/node_modules/multihashes": { + "version": "3.1.2", + "license": "MIT", + "dependencies": { + "multibase": "^3.1.0", + "uint8arrays": "^2.0.5", + "varint": "^6.0.0" + }, + "engines": { + "node": ">=10.0.0", + "npm": ">=6.0.0" + } + }, + "node_modules/libp2p/node_modules/readable-stream": { + "version": "3.6.0", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/libp2p/node_modules/uint8arrays": { + "version": "2.1.10", + "license": "MIT", + "dependencies": { + "multiformats": "^9.4.2" + } + }, + "node_modules/lilconfig": { + "version": "2.0.5", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/lint-staged": { + "version": "13.0.3", + "dev": true, + "license": "MIT", + "dependencies": { + "cli-truncate": "^3.1.0", + "colorette": "^2.0.17", + "commander": "^9.3.0", + "debug": "^4.3.4", + "execa": "^6.1.0", + "lilconfig": "2.0.5", + "listr2": "^4.0.5", + "micromatch": "^4.0.5", + "normalize-path": "^3.0.0", + "object-inspect": "^1.12.2", + "pidtree": "^0.6.0", + "string-argv": "^0.3.1", + "yaml": "^2.1.1" + }, + "bin": { + "lint-staged": "bin/lint-staged.js" + }, + "engines": { + "node": "^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/lint-staged" + } + }, + "node_modules/lint-staged/node_modules/commander": { + "version": "9.4.1", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || >=14" + } + }, + "node_modules/lint-staged/node_modules/execa": { + "version": "6.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.1", + "human-signals": "^3.0.1", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^3.0.7", + "strip-final-newline": "^3.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/lint-staged/node_modules/human-signals": { + "version": "3.0.1", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/lint-staged/node_modules/is-stream": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lint-staged/node_modules/mimic-fn": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lint-staged/node_modules/npm-run-path": { + "version": "5.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lint-staged/node_modules/onetime": { + "version": "6.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-fn": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lint-staged/node_modules/path-key": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lint-staged/node_modules/strip-final-newline": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/listr2": { + "version": "4.0.5", + "dev": true, + "license": "MIT", + "dependencies": { + "cli-truncate": "^2.1.0", + "colorette": "^2.0.16", + "log-update": "^4.0.0", + "p-map": "^4.0.0", + "rfdc": "^1.3.0", + "rxjs": "^7.5.5", + "through": "^2.3.8", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "enquirer": ">= 2.3.0 < 3" + }, + "peerDependenciesMeta": { + "enquirer": { + "optional": true + } + } + }, + "node_modules/listr2/node_modules/cli-truncate": { + "version": "2.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "slice-ansi": "^3.0.0", + "string-width": "^4.2.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/listr2/node_modules/emoji-regex": { + "version": "8.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/listr2/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/listr2/node_modules/slice-ansi": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/listr2/node_modules/string-width": { + "version": "4.2.3", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/lmdb": { + "version": "2.6.8", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "msgpackr": "1.7.2", + "node-addon-api": "^4.3.0", + "node-gyp-build-optional-packages": "5.0.3", + "ordered-binary": "^1.4.0", + "weak-lru-cache": "^1.2.2" + }, + "bin": { + "download-lmdb-prebuilds": "bin/download-prebuilds.js" + }, + "optionalDependencies": { + "@lmdb/lmdb-darwin-arm64": "2.6.8", + "@lmdb/lmdb-darwin-x64": "2.6.8", + "@lmdb/lmdb-linux-arm": "2.6.8", + "@lmdb/lmdb-linux-arm64": "2.6.8", + "@lmdb/lmdb-linux-x64": "2.6.8", + "@lmdb/lmdb-win32-x64": "2.6.8" + } + }, + "node_modules/load-json-file": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/load-json-file/node_modules/strip-bom": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/loader-runner": { + "version": "4.3.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.11.5" + } + }, + "node_modules/loader-utils": { + "version": "2.0.3", + "dev": true, + "license": "MIT", + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + }, + "engines": { + "node": ">=8.9.0" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "license": "MIT" + }, + "node_modules/lodash.camelcase": { + "version": "4.3.0", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.cond": { + "version": "4.5.2", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.debounce": { + "version": "4.0.8", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.find": { + "version": "4.6.0", + "license": "MIT" + }, + "node_modules/lodash.flattendeep": { + "version": "4.4.0", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.get": { + "version": "4.4.2", + "license": "MIT" + }, + "node_modules/lodash.kebabcase": { + "version": "4.1.1", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.max": { + "version": "4.0.1", + "license": "MIT" + }, + "node_modules/lodash.memoize": { + "version": "3.0.4", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "license": "MIT" + }, + "node_modules/lodash.padstart": { + "version": "4.6.1", + "license": "MIT" + }, + "node_modules/lodash.repeat": { + "version": "4.1.0", + "license": "MIT" + }, + "node_modules/lodash.snakecase": { + "version": "4.1.1", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.upperfirst": { + "version": "4.3.1", + "dev": true, + "license": "MIT" + }, + "node_modules/log-update": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-escapes": "^4.3.0", + "cli-cursor": "^3.1.0", + "slice-ansi": "^4.0.0", + "wrap-ansi": "^6.2.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/emoji-regex": { + "version": "8.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/log-update/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/log-update/node_modules/slice-ansi": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/log-update/node_modules/string-width": { + "version": "4.2.3", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/log-update/node_modules/wrap-ansi": { + "version": "6.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/log4js": { + "version": "6.7.0", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "date-format": "^4.0.14", + "debug": "^4.3.4", + "flatted": "^3.2.7", + "rfdc": "^1.3.0", + "streamroller": "^3.1.3" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/logform": { + "version": "2.4.2", + "license": "MIT", + "dependencies": { + "@colors/colors": "1.5.0", + "fecha": "^4.2.0", + "ms": "^2.1.1", + "safe-stable-stringify": "^2.3.1", + "triple-beam": "^1.3.0" + } + }, + "node_modules/logform/node_modules/ms": { + "version": "2.1.3", + "license": "MIT" + }, + "node_modules/lolex": { + "version": "1.6.0", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/long": { + "version": "4.0.0", + "license": "Apache-2.0" + }, + "node_modules/loupe": { + "version": "2.3.4", + "license": "MIT", + "dependencies": { + "get-func-name": "^2.0.0" + } + }, + "node_modules/lower-case": { + "version": "1.1.4", + "dev": true, + "license": "MIT" + }, + "node_modules/lru-cache": { + "version": "7.18.3", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/ltgt": { + "version": "2.2.1", + "dev": true, + "license": "MIT" + }, + "node_modules/lunr": { + "version": "2.3.9", + "dev": true, + "license": "MIT" + }, + "node_modules/mafmt": { + "version": "8.0.4", + "license": "MIT", + "dependencies": { + "multiaddr": "^8.0.0" + } + }, + "node_modules/mafmt/node_modules/multiaddr": { + "version": "8.1.2", + "license": "MIT", + "dependencies": { + "cids": "^1.0.0", + "class-is": "^1.1.0", + "dns-over-http-resolver": "^1.0.0", + "err-code": "^2.0.3", + "is-ip": "^3.1.0", + "multibase": "^3.0.0", + "uint8arrays": "^1.1.0", + "varint": "^5.0.0" + } + }, + "node_modules/mafmt/node_modules/multibase": { + "version": "3.1.2", + "license": "MIT", + "dependencies": { + "@multiformats/base-x": "^4.0.1", + "web-encoding": "^1.0.6" + }, + "engines": { + "node": ">=10.0.0", + "npm": ">=6.0.0" + } + }, + "node_modules/mafmt/node_modules/uint8arrays": { + "version": "1.1.0", + "license": "MIT", + "dependencies": { + "multibase": "^3.0.0", + "web-encoding": "^1.0.2" + } + }, + "node_modules/mafmt/node_modules/varint": { + "version": "5.0.2", + "license": "MIT" + }, + "node_modules/magic-string": { + "version": "0.25.9", + "dev": true, + "license": "MIT", + "dependencies": { + "sourcemap-codec": "^1.4.8" + } + }, + "node_modules/make-dir": { + "version": "1.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "pify": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/make-error": { + "version": "1.3.6", + "dev": true, + "license": "ISC" + }, + "node_modules/marked": { + "version": "4.1.1", + "dev": true, + "license": "MIT", + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 12" + } + }, + "node_modules/mcl-wasm": { + "version": "0.7.9", + "license": "BSD-3-Clause", + "engines": { + "node": ">=8.9.0" + } + }, + "node_modules/md5.js": { + "version": "1.3.5", + "dev": true, + "license": "MIT", + "dependencies": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/memdown": { + "version": "6.1.1", + "dev": true, + "license": "MIT", + "dependencies": { + "abstract-leveldown": "^7.2.0", + "buffer": "^6.0.3", + "functional-red-black-tree": "^1.0.1", + "inherits": "^2.0.1", + "ltgt": "^2.2.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/memory-level": { + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "abstract-level": "^1.0.0", + "functional-red-black-tree": "^1.0.1", + "module-error": "^1.0.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/memorystream": { + "version": "0.3.1", + "dev": true, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/merge-options": { + "version": "3.0.4", + "license": "MIT", + "dependencies": { + "is-plain-obj": "^2.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/merge-source-map": { + "version": "1.0.4", + "dev": true, + "license": "MIT", + "dependencies": { + "source-map": "^0.5.6" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "license": "MIT" + }, + "node_modules/merge2": { + "version": "1.4.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/methods": { + "version": "1.1.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/micro-bmark": { + "version": "0.2.0", + "dev": true, + "license": "MIT" + }, + "node_modules/micromatch": { + "version": "4.0.5", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/miller-rabin": { + "version": "4.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "bn.js": "^4.0.0", + "brorand": "^1.0.1" + }, + "bin": { + "miller-rabin": "bin/miller-rabin" + } + }, + "node_modules/miller-rabin/node_modules/bn.js": { + "version": "4.12.0", + "dev": true, + "license": "MIT" + }, + "node_modules/mime": { + "version": "2.6.0", + "dev": true, + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/minimalistic-assert": { + "version": "1.0.1", + "license": "ISC" + }, + "node_modules/minimalistic-crypto-utils": { + "version": "1.0.1", + "license": "MIT" + }, + "node_modules/minimatch": { + "version": "3.1.2", + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.7", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mkdirp": { + "version": "0.5.6", + "dev": true, + "license": "MIT", + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "dev": true, + "license": "MIT" + }, + "node_modules/module-deps": { + "version": "6.2.3", + "dev": true, + "license": "MIT", + "dependencies": { + "browser-resolve": "^2.0.0", + "cached-path-relative": "^1.0.2", + "concat-stream": "~1.6.0", + "defined": "^1.0.0", + "detective": "^5.2.0", + "duplexer2": "^0.1.2", + "inherits": "^2.0.1", + "JSONStream": "^1.0.3", + "parents": "^1.0.0", + "readable-stream": "^2.0.2", + "resolve": "^1.4.0", + "stream-combiner2": "^1.1.1", + "subarg": "^1.0.0", + "through2": "^2.0.0", + "xtend": "^4.0.0" + }, + "bin": { + "module-deps": "bin/cmd.js" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/module-error": { + "version": "1.0.2", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/moment": { + "version": "2.29.4", + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/morphdom": { + "version": "2.6.1", + "dev": true, + "license": "MIT" + }, + "node_modules/moving-average": { + "version": "1.0.1", + "license": "MIT" + }, + "node_modules/ms": { + "version": "0.7.3", + "license": "MIT" + }, + "node_modules/msgpackr": { + "version": "1.7.2", + "dev": true, + "license": "MIT", + "optionalDependencies": { + "msgpackr-extract": "^2.1.2" + } + }, + "node_modules/msgpackr-extract": { + "version": "2.1.2", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "dependencies": { + "node-gyp-build-optional-packages": "5.0.3" + }, + "bin": { + "download-msgpackr-prebuilds": "bin/download-prebuilds.js" + }, + "optionalDependencies": { + "@msgpackr-extract/msgpackr-extract-darwin-arm64": "2.1.2", + "@msgpackr-extract/msgpackr-extract-darwin-x64": "2.1.2", + "@msgpackr-extract/msgpackr-extract-linux-arm": "2.1.2", + "@msgpackr-extract/msgpackr-extract-linux-arm64": "2.1.2", + "@msgpackr-extract/msgpackr-extract-linux-x64": "2.1.2", + "@msgpackr-extract/msgpackr-extract-win32-x64": "2.1.2" + } + }, + "node_modules/multiaddr": { + "version": "10.0.1", + "license": "MIT", + "dependencies": { + "dns-over-http-resolver": "^1.2.3", + "err-code": "^3.0.1", + "is-ip": "^3.1.0", + "multiformats": "^9.4.5", + "uint8arrays": "^3.0.0", + "varint": "^6.0.0" + } + }, + "node_modules/multiaddr-to-uri": { + "version": "7.0.0", + "license": "MIT", + "dependencies": { + "multiaddr": "^9.0.1" + } + }, + "node_modules/multiaddr-to-uri/node_modules/err-code": { + "version": "3.0.1", + "license": "MIT" + }, + "node_modules/multiaddr-to-uri/node_modules/multiaddr": { + "version": "9.0.2", + "license": "MIT", + "dependencies": { + "cids": "^1.0.0", + "dns-over-http-resolver": "^1.0.0", + "err-code": "^3.0.1", + "is-ip": "^3.1.0", + "multibase": "^4.0.2", + "uint8arrays": "^2.1.3", + "varint": "^6.0.0" + } + }, + "node_modules/multiaddr-to-uri/node_modules/uint8arrays": { + "version": "2.1.10", + "license": "MIT", + "dependencies": { + "multiformats": "^9.4.2" + } + }, + "node_modules/multiaddr/node_modules/err-code": { + "version": "3.0.1", + "license": "MIT" + }, + "node_modules/multibase": { + "version": "4.0.6", + "license": "MIT", + "dependencies": { + "@multiformats/base-x": "^4.0.1" + }, + "engines": { + "node": ">=12.0.0", + "npm": ">=6.0.0" + } + }, + "node_modules/multicodec": { + "version": "2.1.3", + "license": "MIT", + "dependencies": { + "uint8arrays": "1.1.0", + "varint": "^6.0.0" + } + }, + "node_modules/multicodec/node_modules/multibase": { + "version": "3.1.2", + "license": "MIT", + "dependencies": { + "@multiformats/base-x": "^4.0.1", + "web-encoding": "^1.0.6" + }, + "engines": { + "node": ">=10.0.0", + "npm": ">=6.0.0" + } + }, + "node_modules/multicodec/node_modules/uint8arrays": { + "version": "1.1.0", + "license": "MIT", + "dependencies": { + "multibase": "^3.0.0", + "web-encoding": "^1.0.2" + } + }, + "node_modules/multiformats": { + "version": "9.9.0", + "license": "(Apache-2.0 AND MIT)" + }, + "node_modules/multihashes": { + "version": "4.0.3", + "license": "MIT", + "dependencies": { + "multibase": "^4.0.1", + "uint8arrays": "^3.0.0", + "varint": "^5.0.2" + }, + "engines": { + "node": ">=12.0.0", + "npm": ">=6.0.0" + } + }, + "node_modules/multihashes/node_modules/varint": { + "version": "5.0.2", + "license": "MIT" + }, + "node_modules/multihashing-async": { + "version": "2.1.4", + "license": "MIT", + "dependencies": { + "blakejs": "^1.1.0", + "err-code": "^3.0.0", + "js-sha3": "^0.8.0", + "multihashes": "^4.0.1", + "murmurhash3js-revisited": "^3.0.0", + "uint8arrays": "^3.0.0" + }, + "engines": { + "node": ">=12.0.0", + "npm": ">=6.0.0" + } + }, + "node_modules/multihashing-async/node_modules/err-code": { + "version": "3.0.1", + "license": "MIT" + }, + "node_modules/multistream-select": { + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "bl": "^4.0.0", + "debug": "^4.1.1", + "err-code": "^2.0.0", + "it-handshake": "^1.0.2", + "it-length-prefixed": "^3.0.0", + "it-pipe": "^1.0.1", + "it-reader": "^2.0.0", + "p-defer": "^3.0.0", + "uint8arrays": "^1.1.0" + } + }, + "node_modules/multistream-select/node_modules/bl": { + "version": "4.1.0", + "license": "MIT", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/multistream-select/node_modules/buffer": { + "version": "5.7.1", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/multistream-select/node_modules/it-handshake": { + "version": "1.0.2", + "license": "MIT", + "dependencies": { + "it-pushable": "^1.4.0", + "it-reader": "^2.0.0", + "p-defer": "^3.0.0" + } + }, + "node_modules/multistream-select/node_modules/it-length-prefixed": { + "version": "3.1.0", + "license": "MIT", + "dependencies": { + "@types/bl": "^2.1.0", + "bl": "^4.0.2", + "buffer": "^5.5.0", + "varint": "^5.0.0" + } + }, + "node_modules/multistream-select/node_modules/it-reader": { + "version": "2.1.0", + "license": "MIT", + "dependencies": { + "bl": "^4.0.0" + } + }, + "node_modules/multistream-select/node_modules/multibase": { + "version": "3.1.2", + "license": "MIT", + "dependencies": { + "@multiformats/base-x": "^4.0.1", + "web-encoding": "^1.0.6" + }, + "engines": { + "node": ">=10.0.0", + "npm": ">=6.0.0" + } + }, + "node_modules/multistream-select/node_modules/readable-stream": { + "version": "3.6.0", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/multistream-select/node_modules/uint8arrays": { + "version": "1.1.0", + "license": "MIT", + "dependencies": { + "multibase": "^3.0.0", + "web-encoding": "^1.0.2" + } + }, + "node_modules/multistream-select/node_modules/varint": { + "version": "5.0.2", + "license": "MIT" + }, + "node_modules/murmurhash3js-revisited": { + "version": "3.0.0", + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/mutable-proxy": { + "version": "1.0.0", + "license": "MIT", + "engines": { + "node": ">=6.X.X", + "npm": ">=3.X.X" + } + }, + "node_modules/mute-stream": { + "version": "0.0.5", + "dev": true, + "license": "ISC" + }, + "node_modules/mutexify": { + "version": "1.4.0", + "dev": true, + "license": "MIT", + "dependencies": { + "queue-tick": "^1.0.0" + } + }, + "node_modules/nan": { + "version": "2.17.0", + "license": "MIT" + }, + "node_modules/nanoassert": { + "version": "1.1.0", + "dev": true, + "license": "ISC" + }, + "node_modules/nanobench": { + "version": "2.1.1", + "dev": true, + "license": "MIT", + "dependencies": { + "browser-process-hrtime": "^0.1.2", + "chalk": "^1.1.3", + "mutexify": "^1.1.0", + "pretty-hrtime": "^1.0.2" + }, + "bin": { + "nanobench": "run.js", + "nanobench-compare": "compare.js" + } + }, + "node_modules/nanobench/node_modules/ansi-regex": { + "version": "2.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nanobench/node_modules/ansi-styles": { + "version": "2.2.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nanobench/node_modules/chalk": { + "version": "1.1.3", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nanobench/node_modules/strip-ansi": { + "version": "3.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nanobench/node_modules/supports-color": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/nanohtml": { + "version": "1.10.0", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn-node": "^1.8.2", + "camel-case": "^3.0.0", + "convert-source-map": "^1.5.1", + "estree-is-member-expression": "^1.0.0", + "hyperx": "^2.5.0", + "is-boolean-attribute": "0.0.1", + "nanoassert": "^1.1.0", + "nanobench": "^2.1.0", + "normalize-html-whitespace": "^0.2.0", + "through2": "^2.0.3", + "transform-ast": "^2.4.0" + } + }, + "node_modules/nanohtml/node_modules/convert-source-map": { + "version": "1.9.0", + "dev": true, + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.4", + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/napi-macros": { + "version": "2.0.0", + "license": "MIT" + }, + "node_modules/native-abort-controller": { + "version": "1.0.4", + "license": "MIT", + "peerDependencies": { + "abort-controller": "*" + } + }, + "node_modules/native-fetch": { + "version": "3.0.0", + "license": "MIT", + "peerDependencies": { + "node-fetch": "*" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "dev": true, + "license": "MIT" + }, + "node_modules/negotiator": { + "version": "0.6.3", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/neo-async": { + "version": "2.6.2", + "dev": true, + "license": "MIT" + }, + "node_modules/netmask": { + "version": "2.0.2", + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/next-tick": { + "version": "1.1.0", + "dev": true, + "license": "ISC" + }, + "node_modules/nise": { + "version": "4.1.0", + "license": "BSD-3-Clause", + "dependencies": { + "@sinonjs/commons": "^1.7.0", + "@sinonjs/fake-timers": "^6.0.0", + "@sinonjs/text-encoding": "^0.7.1", + "just-extend": "^4.0.2", + "path-to-regexp": "^1.7.0" + } + }, + "node_modules/no-case": { + "version": "2.3.2", + "dev": true, + "license": "MIT", + "dependencies": { + "lower-case": "^1.1.1" + } + }, + "node_modules/noble-ed25519": { + "version": "1.2.6", + "license": "MIT" + }, + "node_modules/noble-secp256k1": { + "version": "1.2.14", + "license": "MIT" + }, + "node_modules/node-addon-api": { + "version": "4.3.0", + "dev": true, + "license": "MIT" + }, + "node_modules/node-dir": { + "version": "0.1.17", + "dev": true, + "license": "MIT", + "dependencies": { + "minimatch": "^3.0.2" + }, + "engines": { + "node": ">= 0.10.5" + } + }, + "node_modules/node-fetch": { + "version": "2.6.7", + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-forge": { + "version": "0.10.0", + "license": "(BSD-3-Clause OR GPL-2.0)", + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/node-gyp-build": { + "version": "4.5.0", + "license": "MIT", + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" + } + }, + "node_modules/node-gyp-build-optional-packages": { + "version": "5.0.3", + "dev": true, + "license": "MIT", + "bin": { + "node-gyp-build-optional-packages": "bin.js", + "node-gyp-build-optional-packages-optional": "optional.js", + "node-gyp-build-optional-packages-test": "build-test.js" + } + }, + "node_modules/node-preload": { + "version": "0.2.1", + "dev": true, + "license": "MIT", + "dependencies": { + "process-on-spawn": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/node-releases": { + "version": "2.0.6", + "dev": true, + "license": "MIT" + }, + "node_modules/normalize-html-whitespace": { + "version": "0.2.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "license": "MIT", + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/number-is-nan": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nyc": { + "version": "15.1.0", + "dev": true, + "license": "ISC", + "dependencies": { + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "caching-transform": "^4.0.0", + "convert-source-map": "^1.7.0", + "decamelize": "^1.2.0", + "find-cache-dir": "^3.2.0", + "find-up": "^4.1.0", + "foreground-child": "^2.0.0", + "get-package-type": "^0.1.0", + "glob": "^7.1.6", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-hook": "^3.0.0", + "istanbul-lib-instrument": "^4.0.0", + "istanbul-lib-processinfo": "^2.0.2", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.0.2", + "make-dir": "^3.0.0", + "node-preload": "^0.2.1", + "p-map": "^3.0.0", + "process-on-spawn": "^1.0.0", + "resolve-from": "^5.0.0", + "rimraf": "^3.0.0", + "signal-exit": "^3.0.2", + "spawn-wrap": "^2.0.0", + "test-exclude": "^6.0.0", + "yargs": "^15.0.2" + }, + "bin": { + "nyc": "bin/nyc.js" + }, + "engines": { + "node": ">=8.9" + } + }, + "node_modules/nyc/node_modules/cliui": { + "version": "6.0.0", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "node_modules/nyc/node_modules/convert-source-map": { + "version": "1.9.0", + "dev": true, + "license": "MIT" + }, + "node_modules/nyc/node_modules/emoji-regex": { + "version": "8.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/nyc/node_modules/find-up": { + "version": "4.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nyc/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/nyc/node_modules/locate-path": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nyc/node_modules/make-dir": { + "version": "3.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/nyc/node_modules/p-limit": { + "version": "2.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/nyc/node_modules/p-locate": { + "version": "4.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nyc/node_modules/p-map": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nyc/node_modules/resolve-from": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/nyc/node_modules/semver": { + "version": "6.3.0", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/nyc/node_modules/string-width": { + "version": "4.2.3", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nyc/node_modules/wrap-ansi": { + "version": "6.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nyc/node_modules/y18n": { + "version": "4.0.3", + "dev": true, + "license": "ISC" + }, + "node_modules/nyc/node_modules/yargs": { + "version": "15.4.1", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nyc/node_modules/yargs-parser": { + "version": "18.1.3", + "dev": true, + "license": "ISC", + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/oauth-sign": { + "version": "0.9.0", + "license": "Apache-2.0", + "engines": { + "node": "*" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-hash": { + "version": "2.2.0", + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/object-inspect": { + "version": "1.12.2", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-is": { + "version": "1.1.5", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.4", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.values": { + "version": "1.1.5", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/on-net-listen": { + "version": "1.1.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=9.4.0 || ^8.9.4" + } + }, + "node_modules/once": { + "version": "1.4.0", + "dev": true, + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/one-time": { + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "fn.name": "1.x.x" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "license": "MIT", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/opn": { + "version": "5.5.0", + "dev": true, + "license": "MIT", + "dependencies": { + "is-wsl": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/opn/node_modules/is-wsl": { + "version": "1.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/optionator": { + "version": "0.9.1", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/ordered-binary": { + "version": "1.4.0", + "dev": true, + "license": "MIT" + }, + "node_modules/os-browserify": { + "version": "0.3.0", + "dev": true, + "license": "MIT" + }, + "node_modules/os-homedir": { + "version": "1.0.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/os-tmpdir": { + "version": "1.0.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/p-any": { + "version": "3.0.0", + "license": "MIT", + "dependencies": { + "p-cancelable": "^2.0.0", + "p-some": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-cancelable": { + "version": "2.1.1", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/p-defer": { + "version": "3.0.0", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/p-fifo": { + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "fast-fifo": "^1.0.0", + "p-defer": "^3.0.0" + } + }, + "node_modules/p-filter": { + "version": "2.1.0", + "license": "MIT", + "dependencies": { + "p-map": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-filter/node_modules/p-map": { + "version": "2.1.0", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/p-finally": { + "version": "1.0.0", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-map": { + "version": "4.0.0", + "license": "MIT", + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-queue": { + "version": "6.6.2", + "license": "MIT", + "dependencies": { + "eventemitter3": "^4.0.4", + "p-timeout": "^3.2.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-queue/node_modules/p-timeout": { + "version": "3.2.0", + "license": "MIT", + "dependencies": { + "p-finally": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-reflect": { + "version": "2.1.0", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/p-retry": { + "version": "4.6.2", + "license": "MIT", + "dependencies": { + "@types/retry": "0.12.0", + "retry": "^0.13.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-settle": { + "version": "4.1.1", + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.2", + "p-reflect": "^2.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-settle/node_modules/p-limit": { + "version": "2.3.0", + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-some": { + "version": "5.0.0", + "license": "MIT", + "dependencies": { + "aggregate-error": "^3.0.0", + "p-cancelable": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-timeout": { + "version": "4.1.0", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/p-times": { + "version": "3.0.0", + "license": "MIT", + "dependencies": { + "p-map": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/p-wait-for": { + "version": "3.2.0", + "license": "MIT", + "dependencies": { + "p-timeout": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-wait-for/node_modules/p-timeout": { + "version": "3.2.0", + "license": "MIT", + "dependencies": { + "p-finally": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/package-hash": { + "version": "4.0.0", + "dev": true, + "license": "ISC", + "dependencies": { + "graceful-fs": "^4.1.15", + "hasha": "^5.0.0", + "lodash.flattendeep": "^4.4.0", + "release-zalgo": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pad": { + "version": "3.2.0", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "wcwidth": "^1.0.1" + }, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/pako": { + "version": "1.0.11", + "dev": true, + "license": "(MIT AND Zlib)" + }, + "node_modules/parent-module": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parents": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "path-platform": "~0.11.15" + } + }, + "node_modules/parse-asn1": { + "version": "5.1.6", + "dev": true, + "license": "ISC", + "dependencies": { + "asn1.js": "^5.2.0", + "browserify-aes": "^1.0.0", + "evp_bytestokey": "^1.0.0", + "pbkdf2": "^3.0.3", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/parse-json": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-browserify": { + "version": "0.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/path-exists": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-is-inside": { + "version": "1.0.2", + "dev": true, + "license": "(WTFPL OR MIT)" + }, + "node_modules/path-key": { + "version": "3.1.1", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "dev": true, + "license": "MIT" + }, + "node_modules/path-platform": { + "version": "0.11.15", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/path-to-regexp": { + "version": "1.8.0", + "license": "MIT", + "dependencies": { + "isarray": "0.0.1" + } + }, + "node_modules/path-to-regexp/node_modules/isarray": { + "version": "0.0.1", + "license": "MIT" + }, + "node_modules/path-type": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/pathval": { + "version": "1.1.1", + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/pbkdf2": { + "version": "3.1.2", + "dev": true, + "license": "MIT", + "dependencies": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + }, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/peer-id": { + "version": "0.14.8", + "license": "MIT", + "dependencies": { + "cids": "^1.1.5", + "class-is": "^1.1.0", + "libp2p-crypto": "^0.19.0", + "minimist": "^1.2.5", + "multihashes": "^4.0.2", + "protobufjs": "^6.10.2", + "uint8arrays": "^2.0.5" + }, + "bin": { + "peer-id": "src/bin.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/peer-id/node_modules/uint8arrays": { + "version": "2.1.10", + "license": "MIT", + "dependencies": { + "multiformats": "^9.4.2" + } + }, + "node_modules/pem-jwk": { + "version": "2.0.0", + "license": "MPL-2.0", + "dependencies": { + "asn1.js": "^5.0.1" + }, + "bin": { + "pem-jwk": "bin/pem-jwk.js" + }, + "engines": { + "node": ">=5.10.0" + } + }, + "node_modules/perf-sym": { + "version": "2.0.3", + "dev": true, + "license": "MIT", + "dependencies": { + "end-of-stream": "^1.1.0", + "minimist": "^1.2.0", + "pump": "^1.0.1", + "resolve-jit-symbols": "^0.5.0", + "split2": "^2.0.1" + }, + "bin": { + "perf-sym": "cmd.js", + "profile_1ms.d": "profile_1ms.d" + } + }, + "node_modules/perf-sym/node_modules/pump": { + "version": "1.0.3", + "dev": true, + "license": "MIT", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/perf-sym/node_modules/split2": { + "version": "2.2.0", + "dev": true, + "license": "ISC", + "dependencies": { + "through2": "^2.0.2" + } + }, + "node_modules/performance-now": { + "version": "2.1.0", + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.0.0", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pidtree": { + "version": "0.6.0", + "dev": true, + "license": "MIT", + "bin": { + "pidtree": "bin/pidtree.js" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/pify": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/pinkie": { + "version": "2.0.4", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pinkie-promise": { + "version": "2.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "pinkie": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pino": { + "version": "5.17.0", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-redact": "^2.0.0", + "fast-safe-stringify": "^2.0.7", + "flatstr": "^1.0.12", + "pino-std-serializers": "^2.4.2", + "quick-format-unescaped": "^3.0.3", + "sonic-boom": "^0.7.5" + }, + "bin": { + "pino": "bin.js" + } + }, + "node_modules/pino-std-serializers": { + "version": "2.5.0", + "dev": true, + "license": "MIT" + }, + "node_modules/pkg-conf": { + "version": "2.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "find-up": "^2.0.0", + "load-json-file": "^4.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pkg-conf/node_modules/find-up": { + "version": "2.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pkg-conf/node_modules/locate-path": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pkg-conf/node_modules/p-limit": { + "version": "1.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-try": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pkg-conf/node_modules/p-locate": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pkg-conf/node_modules/p-try": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/pkg-conf/node_modules/path-exists": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/pkg-config": { + "version": "1.1.1", + "dev": true, + "license": "MIT", + "dependencies": { + "debug-log": "^1.0.0", + "find-root": "^1.0.0", + "xtend": "^4.0.1" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/find-up": { + "version": "4.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/locate-path": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/p-limit": { + "version": "2.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-dir/node_modules/p-locate": { + "version": "4.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-up": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "find-up": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pkg-up/node_modules/find-up": { + "version": "1.1.2", + "dev": true, + "license": "MIT", + "dependencies": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pkg-up/node_modules/path-exists": { + "version": "2.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "pinkie-promise": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/platform": { + "version": "1.3.6", + "dev": true, + "license": "MIT" + }, + "node_modules/pluralize": { + "version": "1.2.1", + "dev": true, + "license": "MIT" + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "2.7.1", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prettier-linter-helpers": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-diff": "^1.1.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/pretty-hrtime": { + "version": "1.0.3", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/pretty-trace": { + "version": "0.3.1", + "dev": true, + "license": "MIT", + "dependencies": { + "ansicolors": "~0.2.1", + "split2": "~0.2.1" + }, + "bin": { + "pretty-trace": "bin/pretty-trace" + } + }, + "node_modules/pretty-trace/node_modules/isarray": { + "version": "0.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/pretty-trace/node_modules/readable-stream": { + "version": "1.0.34", + "dev": true, + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "node_modules/pretty-trace/node_modules/split2": { + "version": "0.2.1", + "dev": true, + "license": "ISC", + "dependencies": { + "through2": "~0.6.1" + } + }, + "node_modules/pretty-trace/node_modules/string_decoder": { + "version": "0.10.31", + "dev": true, + "license": "MIT" + }, + "node_modules/pretty-trace/node_modules/through2": { + "version": "0.6.5", + "dev": true, + "license": "MIT", + "dependencies": { + "readable-stream": ">=1.0.33-1 <1.1.0-0", + "xtend": ">=4.0.0 <4.1.0-0" + } + }, + "node_modules/private-ip": { + "version": "2.3.4", + "license": "MIT", + "dependencies": { + "ip-regex": "^4.3.0", + "ipaddr.js": "^2.0.1", + "is-ip": "^3.1.0", + "netmask": "^2.0.2" + } + }, + "node_modules/process": { + "version": "0.11.10", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/process-on-spawn": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "fromentries": "^1.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/progress": { + "version": "1.1.8", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/promise-to-callback": { + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "is-fn": "^1.0.0", + "set-immediate-shim": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/protobufjs": { + "version": "6.11.3", + "hasInstallScript": true, + "license": "BSD-3-Clause", + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/long": "^4.0.1", + "@types/node": ">=13.7.0", + "long": "^4.0.0" + }, + "bin": { + "pbjs": "bin/pbjs", + "pbts": "bin/pbts" + } + }, + "node_modules/protocol-buffers-schema": { + "version": "3.6.0", + "license": "MIT" + }, + "node_modules/protons": { + "version": "2.0.3", + "license": "MIT", + "dependencies": { + "protocol-buffers-schema": "^3.3.1", + "signed-varint": "^2.0.1", + "uint8arrays": "^3.0.0", + "varint": "^5.0.0" + } + }, + "node_modules/protons/node_modules/varint": { + "version": "5.0.2", + "license": "MIT" + }, + "node_modules/psl": { + "version": "1.9.0", + "license": "MIT" + }, + "node_modules/public-encrypt": { + "version": "4.0.3", + "dev": true, + "license": "MIT", + "dependencies": { + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/public-encrypt/node_modules/bn.js": { + "version": "4.12.0", + "dev": true, + "license": "MIT" + }, + "node_modules/pump": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/pumpify": { + "version": "1.5.1", + "dev": true, + "license": "MIT", + "dependencies": { + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" + } + }, + "node_modules/pumpify/node_modules/pump": { + "version": "2.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/punycode": { + "version": "1.4.1", + "dev": true, + "license": "MIT" + }, + "node_modules/qheap": { + "version": "1.4.0", + "license": "Apache-2.0", + "engines": { + "node": "*" + } + }, + "node_modules/qjobs": { + "version": "1.2.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.9" + } + }, + "node_modules/qs": { + "version": "6.11.0", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/querystring": { + "version": "0.2.0", + "dev": true, + "engines": { + "node": ">=0.4.x" + } + }, + "node_modules/querystring-es3": { + "version": "0.2.1", + "dev": true, + "engines": { + "node": ">=0.4.x" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/queue-tick": { + "version": "1.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/quibble": { + "version": "0.6.17", + "dev": true, + "license": "MIT", + "dependencies": { + "lodash": "^4.17.21", + "resolve": "^1.22.1" + }, + "engines": { + "node": ">= 0.14.0" + } + }, + "node_modules/quick-format-unescaped": { + "version": "3.0.3", + "dev": true, + "license": "MIT" + }, + "node_modules/randombytes": { + "version": "2.1.0", + "license": "MIT", + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/randomfill": { + "version": "1.0.4", + "dev": true, + "license": "MIT", + "dependencies": { + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.1", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/react-native-fetch-api": { + "version": "2.0.0", + "license": "MIT", + "dependencies": { + "p-defer": "^3.0.0" + } + }, + "node_modules/read-only-stream": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "readable-stream": "^2.0.2" + } + }, + "node_modules/readable-stream": { + "version": "2.3.7", + "dev": true, + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/readable-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "dev": true, + "license": "MIT" + }, + "node_modules/readable-stream/node_modules/string_decoder": { + "version": "1.1.1", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "dev": true, + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/readline2": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "mute-stream": "0.0.5" + } + }, + "node_modules/readline2/node_modules/is-fullwidth-code-point": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "number-is-nan": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/receptacle": { + "version": "1.3.2", + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/receptacle/node_modules/ms": { + "version": "2.1.3", + "license": "MIT" + }, + "node_modules/rechoir": { + "version": "0.7.1", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve": "^1.9.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/regenerate": { + "version": "1.4.2", + "dev": true, + "license": "MIT" + }, + "node_modules/regenerate-unicode-properties": { + "version": "10.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "regenerate": "^1.4.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.13.10", + "dev": true, + "license": "MIT" + }, + "node_modules/regenerator-transform": { + "version": "0.15.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.8.4" + } + }, + "node_modules/regexp.prototype.flags": { + "version": "1.4.3", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "functions-have-names": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regexpp": { + "version": "3.2.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + } + }, + "node_modules/regexpu-core": { + "version": "5.2.1", + "dev": true, + "license": "MIT", + "dependencies": { + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.1.0", + "regjsgen": "^0.7.1", + "regjsparser": "^0.9.1", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regjsgen": { + "version": "0.7.1", + "dev": true, + "license": "MIT" + }, + "node_modules/regjsparser": { + "version": "0.9.1", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "jsesc": "~0.5.0" + }, + "bin": { + "regjsparser": "bin/parser" + } + }, + "node_modules/regjsparser/node_modules/jsesc": { + "version": "0.5.0", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + } + }, + "node_modules/release-zalgo": { + "version": "1.0.0", + "dev": true, + "license": "ISC", + "dependencies": { + "es6-error": "^4.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/request": { + "version": "2.88.2", + "license": "Apache-2.0", + "dependencies": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/request/node_modules/qs": { + "version": "6.5.3", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/request/node_modules/uuid": { + "version": "3.4.0", + "license": "MIT", + "bin": { + "uuid": "bin/uuid" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-main-filename": { + "version": "2.0.0", + "dev": true, + "license": "ISC" + }, + "node_modules/require-uncached": { + "version": "1.0.3", + "dev": true, + "license": "MIT", + "dependencies": { + "caller-path": "^0.1.0", + "resolve-from": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-uncached/node_modules/resolve-from": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/requires-port": { + "version": "1.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/resolve": { + "version": "1.22.1", + "dev": true, + "license": "MIT", + "dependencies": { + "is-core-module": "^2.9.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-cwd": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-cwd/node_modules/resolve-from": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/resolve-jit-symbols": { + "version": "0.5.0", + "dev": true, + "license": "MIT", + "dependencies": { + "pretty-trace": "~0.3.1" + }, + "bin": { + "rjs": "bin/rjs" + } + }, + "node_modules/restore-cursor": { + "version": "3.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/resumer": { + "version": "0.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "through": "~2.3.4" + } + }, + "node_modules/retimer": { + "version": "2.0.0", + "license": "MIT" + }, + "node_modules/retry": { + "version": "0.13.1", + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rfdc": { + "version": "1.3.0", + "dev": true, + "license": "MIT" + }, + "node_modules/rimraf": { + "version": "3.0.2", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/ripemd160": { + "version": "2.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "node_modules/run-async": { + "version": "0.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "once": "^1.3.0" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/run-parallel-limit": { + "version": "1.1.0", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/rustbn.js": { + "version": "0.2.0", + "license": "(MIT OR Apache-2.0)" + }, + "node_modules/rx-lite": { + "version": "3.1.2", + "dev": true + }, + "node_modules/rxjs": { + "version": "7.5.7", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/safe-regex-test": { + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "is-regex": "^1.1.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-stable-stringify": { + "version": "2.4.1", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "license": "MIT" + }, + "node_modules/sanitize-filename": { + "version": "1.6.3", + "license": "WTFPL OR ISC", + "dependencies": { + "truncate-utf8-bytes": "^1.0.0" + } + }, + "node_modules/sax": { + "version": "1.2.4", + "license": "ISC" + }, + "node_modules/scanf": { + "version": "1.1.2", + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/schema-utils": { + "version": "2.7.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/json-schema": "^7.0.5", + "ajv": "^6.12.4", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 8.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/scrypt-js": { + "version": "3.0.1", + "license": "MIT" + }, + "node_modules/secp256k1": { + "version": "4.0.3", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "elliptic": "^6.5.4", + "node-addon-api": "^2.0.0", + "node-gyp-build": "^4.2.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/secp256k1/node_modules/node-addon-api": { + "version": "2.0.2", + "license": "MIT" + }, + "node_modules/semver": { + "version": "7.3.8", + "dev": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver/node_modules/lru-cache": { + "version": "6.0.0", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver/node_modules/yallist": { + "version": "4.0.0", + "dev": true, + "license": "ISC" + }, + "node_modules/serialize-javascript": { + "version": "6.0.0", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "dev": true, + "license": "ISC" + }, + "node_modules/set-delayed-interval": { + "version": "1.0.0", + "license": "MIT" + }, + "node_modules/set-immediate-shim": { + "version": "1.0.1", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/setimmediate": { + "version": "1.0.5", + "dev": true, + "license": "MIT" + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "license": "ISC" + }, + "node_modules/sha.js": { + "version": "2.4.11", + "dev": true, + "license": "(MIT AND BSD-3-Clause)", + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + }, + "bin": { + "sha.js": "bin.js" + } + }, + "node_modules/shallow-clone": { + "version": "3.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shasum": { + "version": "1.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "json-stable-stringify": "~0.0.0", + "sha.js": "~2.4.4" + } + }, + "node_modules/shasum-object": { + "version": "1.0.0", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "fast-safe-stringify": "^2.0.7" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/shell-quote": { + "version": "1.7.4", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/shelljs": { + "version": "0.7.8", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "glob": "^7.0.0", + "interpret": "^1.0.0", + "rechoir": "^0.6.2" + }, + "bin": { + "shjs": "bin/shjs" + }, + "engines": { + "iojs": "*", + "node": ">=0.11.0" + } + }, + "node_modules/shelljs/node_modules/interpret": { + "version": "1.4.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/shelljs/node_modules/rechoir": { + "version": "0.6.2", + "dev": true, + "dependencies": { + "resolve": "^1.1.6" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/shiki": { + "version": "0.10.1", + "dev": true, + "license": "MIT", + "dependencies": { + "jsonc-parser": "^3.0.0", + "vscode-oniguruma": "^1.6.1", + "vscode-textmate": "5.2.0" + } + }, + "node_modules/side-channel": { + "version": "1.0.4", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "license": "ISC" + }, + "node_modules/signed-varint": { + "version": "2.0.1", + "license": "MIT", + "dependencies": { + "varint": "~5.0.0" + } + }, + "node_modules/signed-varint/node_modules/varint": { + "version": "5.0.2", + "license": "MIT" + }, + "node_modules/simple-concat": { + "version": "1.0.1", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/simple-swizzle": { + "version": "0.2.2", + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.3.1" + } + }, + "node_modules/simple-swizzle/node_modules/is-arrayish": { + "version": "0.3.2", + "license": "MIT" + }, + "node_modules/single-line-log": { + "version": "1.1.2", + "dev": true, + "license": "MIT", + "dependencies": { + "string-width": "^1.0.1" + } + }, + "node_modules/single-line-log/node_modules/ansi-regex": { + "version": "2.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/single-line-log/node_modules/is-fullwidth-code-point": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "number-is-nan": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/single-line-log/node_modules/string-width": { + "version": "1.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/single-line-log/node_modules/strip-ansi": { + "version": "3.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sinon": { + "version": "9.2.4", + "license": "BSD-3-Clause", + "dependencies": { + "@sinonjs/commons": "^1.8.1", + "@sinonjs/fake-timers": "^6.0.1", + "@sinonjs/samsam": "^5.3.1", + "diff": "^4.0.2", + "nise": "^4.0.4", + "supports-color": "^7.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/sinon" + } + }, + "node_modules/slash": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/slice-ansi": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.0.0", + "is-fullwidth-code-point": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/slice-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/snappyjs": { + "version": "0.6.1", + "license": "MIT" + }, + "node_modules/socket.io": { + "version": "4.5.3", + "dev": true, + "license": "MIT", + "dependencies": { + "accepts": "~1.3.4", + "base64id": "~2.0.0", + "debug": "~4.3.2", + "engine.io": "~6.2.0", + "socket.io-adapter": "~2.4.0", + "socket.io-parser": "~4.2.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/socket.io-adapter": { + "version": "2.4.0", + "dev": true, + "license": "MIT" + }, + "node_modules/socket.io-parser": { + "version": "4.2.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/solc": { + "version": "0.8.17", + "dev": true, + "license": "MIT", + "dependencies": { + "command-exists": "^1.2.8", + "commander": "^8.1.0", + "follow-redirects": "^1.12.1", + "js-sha3": "0.8.0", + "memorystream": "^0.3.1", + "semver": "^5.5.0", + "tmp": "0.0.33" + }, + "bin": { + "solcjs": "solc.js" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/solc/node_modules/commander": { + "version": "8.3.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, + "node_modules/solc/node_modules/semver": { + "version": "5.7.1", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/solc/node_modules/tmp": { + "version": "0.0.33", + "dev": true, + "license": "MIT", + "dependencies": { + "os-tmpdir": "~1.0.2" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/sonic-boom": { + "version": "0.7.7", + "dev": true, + "license": "MIT", + "dependencies": { + "atomic-sleep": "^1.0.0", + "flatstr": "^1.0.12" + } + }, + "node_modules/sort-object-keys": { + "version": "1.1.3", + "dev": true, + "license": "MIT" + }, + "node_modules/sort-package-json": { + "version": "1.57.0", + "dev": true, + "license": "MIT", + "dependencies": { + "detect-indent": "^6.0.0", + "detect-newline": "3.1.0", + "git-hooks-list": "1.0.3", + "globby": "10.0.0", + "is-plain-obj": "2.1.0", + "sort-object-keys": "^1.1.3" + }, + "bin": { + "sort-package-json": "cli.js" + } + }, + "node_modules/sort-package-json/node_modules/globby": { + "version": "10.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/glob": "^7.1.1", + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.0.3", + "glob": "^7.1.3", + "ignore": "^5.1.1", + "merge2": "^1.2.3", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/source-map": { + "version": "0.5.7", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/source-map-support/node_modules/source-map": { + "version": "0.6.1", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sourcemap-codec": { + "version": "1.4.8", + "dev": true, + "license": "MIT" + }, + "node_modules/spawn-wrap": { + "version": "2.0.0", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^2.0.0", + "is-windows": "^1.0.2", + "make-dir": "^3.0.0", + "rimraf": "^3.0.0", + "signal-exit": "^3.0.2", + "which": "^2.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/spawn-wrap/node_modules/make-dir": { + "version": "3.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/spawn-wrap/node_modules/semver": { + "version": "6.3.0", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/spawn-wrap/node_modules/which": { + "version": "2.0.2", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/split2": { + "version": "3.2.2", + "dev": true, + "license": "ISC", + "dependencies": { + "readable-stream": "^3.0.0" + } + }, + "node_modules/split2/node_modules/readable-stream": { + "version": "3.6.0", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/sprintf-js": { + "version": "1.1.2", + "license": "BSD-3-Clause" + }, + "node_modules/sshpk": { + "version": "1.17.0", + "license": "MIT", + "dependencies": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + }, + "bin": { + "sshpk-conv": "bin/sshpk-conv", + "sshpk-sign": "bin/sshpk-sign", + "sshpk-verify": "bin/sshpk-verify" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sshpk/node_modules/jsbn": { + "version": "0.1.1", + "license": "MIT" + }, + "node_modules/stack-trace": { + "version": "0.0.10", + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/standard": { + "version": "10.0.3", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint": "~3.19.0", + "eslint-config-standard": "10.2.1", + "eslint-config-standard-jsx": "4.0.2", + "eslint-plugin-import": "~2.2.0", + "eslint-plugin-node": "~4.2.2", + "eslint-plugin-promise": "~3.5.0", + "eslint-plugin-react": "~6.10.0", + "eslint-plugin-standard": "~3.0.1", + "standard-engine": "~7.0.0" + }, + "bin": { + "standard": "bin/cmd.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/standard-engine": { + "version": "7.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "deglob": "^2.1.0", + "get-stdin": "^5.0.1", + "minimist": "^1.1.0", + "pkg-conf": "^2.0.0" + } + }, + "node_modules/standard/node_modules/acorn": { + "version": "5.7.4", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/standard/node_modules/acorn-jsx": { + "version": "3.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^3.0.4" + } + }, + "node_modules/standard/node_modules/acorn-jsx/node_modules/acorn": { + "version": "3.3.0", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/standard/node_modules/ansi-regex": { + "version": "2.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/standard/node_modules/ansi-styles": { + "version": "2.2.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/standard/node_modules/argparse": { + "version": "1.0.10", + "dev": true, + "license": "MIT", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/standard/node_modules/chalk": { + "version": "1.1.3", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/standard/node_modules/debug": { + "version": "2.6.9", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/standard/node_modules/doctrine": { + "version": "2.1.0", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/standard/node_modules/eslint": { + "version": "3.19.0", + "dev": true, + "license": "MIT", + "dependencies": { + "babel-code-frame": "^6.16.0", + "chalk": "^1.1.3", + "concat-stream": "^1.5.2", + "debug": "^2.1.1", + "doctrine": "^2.0.0", + "escope": "^3.6.0", + "espree": "^3.4.0", + "esquery": "^1.0.0", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "file-entry-cache": "^2.0.0", + "glob": "^7.0.3", + "globals": "^9.14.0", + "ignore": "^3.2.0", + "imurmurhash": "^0.1.4", + "inquirer": "^0.12.0", + "is-my-json-valid": "^2.10.0", + "is-resolvable": "^1.0.0", + "js-yaml": "^3.5.1", + "json-stable-stringify": "^1.0.0", + "levn": "^0.3.0", + "lodash": "^4.0.0", + "mkdirp": "^0.5.0", + "natural-compare": "^1.4.0", + "optionator": "^0.8.2", + "path-is-inside": "^1.0.1", + "pluralize": "^1.2.1", + "progress": "^1.1.8", + "require-uncached": "^1.0.2", + "shelljs": "^0.7.5", + "strip-bom": "^3.0.0", + "strip-json-comments": "~2.0.1", + "table": "^3.7.8", + "text-table": "~0.2.0", + "user-home": "^2.0.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/standard/node_modules/eslint-config-standard-jsx": { + "version": "4.0.2", + "dev": true, + "license": "MIT", + "peerDependencies": { + "eslint": ">=3.19.0", + "eslint-plugin-react": ">=6.10.3" + } + }, + "node_modules/standard/node_modules/eslint-import-resolver-node": { + "version": "0.2.3", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^2.2.0", + "object-assign": "^4.0.1", + "resolve": "^1.1.6" + } + }, + "node_modules/standard/node_modules/eslint-plugin-import": { + "version": "2.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "builtin-modules": "^1.1.1", + "contains-path": "^0.1.0", + "debug": "^2.2.0", + "doctrine": "1.5.0", + "eslint-import-resolver-node": "^0.2.0", + "eslint-module-utils": "^2.0.0", + "has": "^1.0.1", + "lodash.cond": "^4.3.0", + "minimatch": "^3.0.3", + "pkg-up": "^1.0.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "2.x - 3.x" + } + }, + "node_modules/standard/node_modules/eslint-plugin-import/node_modules/doctrine": { + "version": "1.5.0", + "dev": true, + "dependencies": { + "esutils": "^2.0.2", + "isarray": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/standard/node_modules/eslint-plugin-react": { + "version": "6.10.3", + "dev": true, + "license": "MIT", + "dependencies": { + "array.prototype.find": "^2.0.1", + "doctrine": "^1.2.2", + "has": "^1.0.1", + "jsx-ast-utils": "^1.3.4", + "object.assign": "^4.0.4" + }, + "engines": { + "node": ">=0.10" + }, + "peerDependencies": { + "eslint": "^2.0.0 || ^3.0.0" + } + }, + "node_modules/standard/node_modules/eslint-plugin-react/node_modules/doctrine": { + "version": "1.5.0", + "dev": true, + "dependencies": { + "esutils": "^2.0.2", + "isarray": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/standard/node_modules/espree": { + "version": "3.5.4", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^5.5.0", + "acorn-jsx": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/standard/node_modules/file-entry-cache": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^1.2.1", + "object-assign": "^4.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/standard/node_modules/flat-cache": { + "version": "1.3.4", + "dev": true, + "license": "MIT", + "dependencies": { + "circular-json": "^0.3.1", + "graceful-fs": "^4.1.2", + "rimraf": "~2.6.2", + "write": "^0.2.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/standard/node_modules/globals": { + "version": "9.18.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/standard/node_modules/ignore": { + "version": "3.3.10", + "dev": true, + "license": "MIT" + }, + "node_modules/standard/node_modules/js-yaml": { + "version": "3.14.1", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/standard/node_modules/json-stable-stringify": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "jsonify": "~0.0.0" + } + }, + "node_modules/standard/node_modules/jsx-ast-utils": { + "version": "1.4.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/standard/node_modules/levn": { + "version": "0.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/standard/node_modules/ms": { + "version": "2.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/standard/node_modules/optionator": { + "version": "0.8.3", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/standard/node_modules/prelude-ls": { + "version": "1.1.2", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/standard/node_modules/rimraf": { + "version": "2.6.3", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/standard/node_modules/sprintf-js": { + "version": "1.0.3", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/standard/node_modules/strip-ansi": { + "version": "3.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/standard/node_modules/strip-bom": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/standard/node_modules/strip-json-comments": { + "version": "2.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/standard/node_modules/supports-color": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/standard/node_modules/type-check": { + "version": "0.3.2", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/statuses": { + "version": "1.5.0", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/stream-browserify": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "~2.0.4", + "readable-stream": "^3.5.0" + } + }, + "node_modules/stream-browserify/node_modules/readable-stream": { + "version": "3.6.0", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/stream-combiner2": { + "version": "1.1.1", + "dev": true, + "license": "MIT", + "dependencies": { + "duplexer2": "~0.1.0", + "readable-stream": "^2.0.2" + } + }, + "node_modules/stream-http": { + "version": "3.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "builtin-status-codes": "^3.0.0", + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "xtend": "^4.0.2" + } + }, + "node_modules/stream-http/node_modules/readable-stream": { + "version": "3.6.0", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/stream-shift": { + "version": "1.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/stream-splicer": { + "version": "2.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.2" + } + }, + "node_modules/stream-to-it": { + "version": "0.2.4", + "license": "MIT", + "dependencies": { + "get-iterator": "^1.0.2" + } + }, + "node_modules/streaming-iterables": { + "version": "5.0.4", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/streamroller": { + "version": "3.1.3", + "dev": true, + "license": "MIT", + "dependencies": { + "date-format": "^4.0.14", + "debug": "^4.3.4", + "fs-extra": "^8.1.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/streamroller/node_modules/fs-extra": { + "version": "8.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/streamroller/node_modules/jsonfile": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/streamroller/node_modules/universalify": { + "version": "0.1.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-argv": { + "version": "0.3.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.6.19" + } + }, + "node_modules/string-width": { + "version": "5.1.2", + "dev": true, + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width/node_modules/ansi-regex": { + "version": "6.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/string-width/node_modules/strip-ansi": { + "version": "7.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.6", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.19.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.5", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.19.5" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.5", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.19.5" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/stringify-object-es5": { + "version": "2.5.0", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "is-plain-obj": "^1.0.0", + "is-regexp": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stringify-object-es5/node_modules/is-plain-obj": { + "version": "1.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/subarg": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "minimist": "^1.1.0" + } + }, + "node_modules/superagent": { + "version": "8.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "component-emitter": "^1.3.0", + "cookiejar": "^2.1.3", + "debug": "^4.3.4", + "fast-safe-stringify": "^2.1.1", + "form-data": "^4.0.0", + "formidable": "^2.0.1", + "methods": "^1.1.2", + "mime": "2.6.0", + "qs": "^6.11.0", + "semver": "^7.3.7" + }, + "engines": { + "node": ">=6.4.0 <13 || >=14" + } + }, + "node_modules/superagent/node_modules/form-data": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/supertest": { + "version": "6.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "methods": "^1.1.2", + "superagent": "^8.0.0" + }, + "engines": { + "node": ">=6.4.0" + } + }, + "node_modules/superwstest": { + "version": "2.0.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/supertest": "<7", + "@types/ws": "7.x || 8.x", + "ws": "7.x || 8.x" + }, + "peerDependencies": { + "supertest": "*" + }, + "peerDependenciesMeta": { + "supertest": { + "optional": true + } + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/svg-element-attributes": { + "version": "1.3.1", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/syntax-error": { + "version": "1.4.0", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn-node": "^1.2.0" + } + }, + "node_modules/table": { + "version": "3.8.3", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "ajv": "^4.7.0", + "ajv-keywords": "^1.0.0", + "chalk": "^1.1.1", + "lodash": "^4.0.0", + "slice-ansi": "0.0.4", + "string-width": "^2.0.0" + } + }, + "node_modules/table/node_modules/ajv": { + "version": "4.11.8", + "dev": true, + "license": "MIT", + "dependencies": { + "co": "^4.6.0", + "json-stable-stringify": "^1.0.1" + } + }, + "node_modules/table/node_modules/ajv-keywords": { + "version": "1.5.1", + "dev": true, + "license": "MIT", + "peerDependencies": { + "ajv": ">=4.10.0" + } + }, + "node_modules/table/node_modules/ansi-regex": { + "version": "2.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/table/node_modules/ansi-styles": { + "version": "2.2.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/table/node_modules/chalk": { + "version": "1.1.3", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/table/node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/table/node_modules/json-stable-stringify": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "jsonify": "~0.0.0" + } + }, + "node_modules/table/node_modules/slice-ansi": { + "version": "0.0.4", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/table/node_modules/string-width": { + "version": "2.1.1", + "dev": true, + "license": "MIT", + "dependencies": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/table/node_modules/string-width/node_modules/ansi-regex": { + "version": "3.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/table/node_modules/string-width/node_modules/strip-ansi": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/table/node_modules/strip-ansi": { + "version": "3.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/table/node_modules/supports-color": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/tachyons": { + "version": "4.12.0", + "dev": true, + "license": "MIT" + }, + "node_modules/tapable": { + "version": "2.2.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/tape": { + "version": "5.6.0", + "dev": true, + "license": "MIT", + "dependencies": { + "array.prototype.every": "^1.1.3", + "call-bind": "^1.0.2", + "deep-equal": "^2.0.5", + "defined": "^1.0.0", + "dotignore": "^0.1.2", + "for-each": "^0.3.3", + "get-package-type": "^0.1.0", + "glob": "^7.2.3", + "has": "^1.0.3", + "has-dynamic-import": "^2.0.1", + "inherits": "^2.0.4", + "is-regex": "^1.1.4", + "minimist": "^1.2.6", + "object-inspect": "^1.12.2", + "object-is": "^1.1.5", + "object-keys": "^1.1.1", + "object.assign": "^4.1.3", + "resolve": "^2.0.0-next.3", + "resumer": "^0.0.0", + "string.prototype.trim": "^1.2.6", + "through": "^2.3.8" + }, + "bin": { + "tape": "bin/tape" + } + }, + "node_modules/tape/node_modules/resolve": { + "version": "2.0.0-next.4", + "dev": true, + "license": "MIT", + "dependencies": { + "is-core-module": "^2.9.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/terser": { + "version": "5.15.1", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@jridgewell/source-map": "^0.3.2", + "acorn": "^8.5.0", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser-webpack-plugin": { + "version": "5.3.6", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.14", + "jest-worker": "^27.4.5", + "schema-utils": "^3.1.1", + "serialize-javascript": "^6.0.0", + "terser": "^5.14.1" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "uglify-js": { + "optional": true + } + } + }, + "node_modules/terser-webpack-plugin/node_modules/schema-utils": { + "version": "3.1.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/terser/node_modules/commander": { + "version": "2.20.3", + "dev": true, + "license": "MIT" + }, + "node_modules/test-exclude": { + "version": "6.0.0", + "dev": true, + "license": "ISC", + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/testdouble": { + "version": "3.17.2", + "dev": true, + "license": "MIT", + "dependencies": { + "lodash": "^4.17.21", + "quibble": "^0.6.17", + "stringify-object-es5": "^2.5.0", + "theredoc": "^1.0.0" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/testdouble-timers": { + "version": "0.1.1", + "dev": true, + "license": "MIT", + "dependencies": { + "lolex": "^1.4.0" + }, + "peerDependencies": { + "testdouble": "^3.0.0" + } + }, + "node_modules/text-hex": { + "version": "1.0.0", + "license": "MIT" + }, + "node_modules/text-table": { + "version": "0.2.0", + "dev": true, + "license": "MIT" + }, + "node_modules/theredoc": { + "version": "1.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/through": { + "version": "2.3.8", + "license": "MIT" + }, + "node_modules/through2": { + "version": "2.0.5", + "dev": true, + "license": "MIT", + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/timeout-abort-controller": { + "version": "1.1.1", + "license": "MIT", + "dependencies": { + "abort-controller": "^3.0.0", + "retimer": "^2.0.0" + } + }, + "node_modules/timers-browserify": { + "version": "1.4.2", + "dev": true, + "dependencies": { + "process": "~0.11.0" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/tmp": { + "version": "0.2.1", + "dev": true, + "license": "MIT", + "dependencies": { + "rimraf": "^3.0.0" + }, + "engines": { + "node": ">=8.17.0" + } + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/tough-cookie": { + "version": "2.5.0", + "license": "BSD-3-Clause", + "dependencies": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/tough-cookie/node_modules/punycode": { + "version": "2.1.1", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "license": "MIT" + }, + "node_modules/transform-ast": { + "version": "2.4.4", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn-node": "^1.3.0", + "convert-source-map": "^1.5.1", + "dash-ast": "^1.0.0", + "is-buffer": "^2.0.0", + "magic-string": "^0.23.2", + "merge-source-map": "1.0.4", + "nanobench": "^2.1.1" + } + }, + "node_modules/transform-ast/node_modules/convert-source-map": { + "version": "1.9.0", + "dev": true, + "license": "MIT" + }, + "node_modules/transform-ast/node_modules/magic-string": { + "version": "0.23.2", + "dev": true, + "license": "MIT", + "dependencies": { + "sourcemap-codec": "^1.4.1" + } + }, + "node_modules/triple-beam": { + "version": "1.3.0", + "license": "MIT" + }, + "node_modules/truncate-utf8-bytes": { + "version": "1.0.2", + "license": "WTFPL", + "dependencies": { + "utf8-byte-length": "^1.0.1" + } + }, + "node_modules/ts-node": { + "version": "10.9.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/ts-node/node_modules/acorn-walk": { + "version": "8.2.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/tsconfig-paths": { + "version": "3.14.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.1", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } + }, + "node_modules/tsconfig-paths/node_modules/json5": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/tsconfig-paths/node_modules/strip-bom": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/tslib": { + "version": "2.4.0", + "dev": true, + "license": "0BSD" + }, + "node_modules/tsutils": { + "version": "3.21.0", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^1.8.1" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + } + }, + "node_modules/tsutils/node_modules/tslib": { + "version": "1.14.1", + "dev": true, + "license": "0BSD" + }, + "node_modules/tty-browserify": { + "version": "0.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/tweetnacl": { + "version": "0.14.5", + "license": "Unlicense" + }, + "node_modules/type": { + "version": "1.2.0", + "dev": true, + "license": "ISC" + }, + "node_modules/type-check": { + "version": "0.4.0", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-component": { + "version": "0.0.1", + "dev": true + }, + "node_modules/type-detect": { + "version": "4.0.8", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "license": "MIT", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typedarray": { + "version": "0.0.6", + "dev": true, + "license": "MIT" + }, + "node_modules/typedarray-to-buffer": { + "version": "3.1.5", + "dev": true, + "license": "MIT", + "dependencies": { + "is-typedarray": "^1.0.0" + } + }, + "node_modules/typedoc": { + "version": "0.23.10", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "lunr": "^2.3.9", + "marked": "^4.0.18", + "minimatch": "^5.1.0", + "shiki": "^0.10.1" + }, + "bin": { + "typedoc": "bin/typedoc" + }, + "engines": { + "node": ">= 14.14" + }, + "peerDependencies": { + "typescript": "4.6.x || 4.7.x" + } + }, + "node_modules/typedoc-plugin-markdown": { + "version": "3.13.4", + "dev": true, + "license": "MIT", + "dependencies": { + "handlebars": "^4.7.7" + }, + "peerDependencies": { + "typedoc": ">=0.23.0" + } + }, + "node_modules/typedoc/node_modules/brace-expansion": { + "version": "2.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/typedoc/node_modules/minimatch": { + "version": "5.1.0", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/typescript": { + "version": "4.7.4", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/ua-parser-js": { + "version": "0.7.32", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/ua-parser-js" + }, + { + "type": "paypal", + "url": "https://paypal.me/faisalman" + } + ], + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/uglify-js": { + "version": "3.17.3", + "dev": true, + "license": "BSD-2-Clause", + "optional": true, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/uint8arrays": { + "version": "3.1.1", + "license": "MIT", + "dependencies": { + "multiformats": "^9.4.2" + } + }, + "node_modules/umd": { + "version": "3.0.3", + "dev": true, + "license": "MIT", + "bin": { + "umd": "bin/cli.js" + } + }, + "node_modules/unbox-primitive": { + "version": "1.0.2", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/undeclared-identifiers": { + "version": "1.1.3", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "acorn-node": "^1.3.0", + "dash-ast": "^1.0.0", + "get-assigned-identifiers": "^1.2.0", + "simple-concat": "^1.0.0", + "xtend": "^4.0.1" + }, + "bin": { + "undeclared-identifiers": "bin.js" + } + }, + "node_modules/unicode-canonical-property-names-ecmascript": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-ecmascript": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-value-ecmascript": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-property-aliases-ecmascript": { + "version": "2.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/uniq": { + "version": "1.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/universalify": { + "version": "2.0.0", + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/unordered-array-remove": { + "version": "1.0.2", + "license": "MIT" + }, + "node_modules/unpipe": { + "version": "1.0.0", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.0.10", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + }, + "bin": { + "browserslist-lint": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/upper-case": { + "version": "1.1.3", + "dev": true, + "license": "MIT" + }, + "node_modules/uri-js": { + "version": "4.4.1", + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/uri-js/node_modules/punycode": { + "version": "2.1.1", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/url": { + "version": "0.11.0", + "dev": true, + "license": "MIT", + "dependencies": { + "punycode": "1.3.2", + "querystring": "0.2.0" + } + }, + "node_modules/url/node_modules/punycode": { + "version": "1.3.2", + "dev": true, + "license": "MIT" + }, + "node_modules/ursa-optional": { + "version": "0.10.2", + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "bindings": "^1.5.0", + "nan": "^2.14.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/user-home": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "os-homedir": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/utf8-byte-length": { + "version": "1.0.4", + "license": "WTFPL" + }, + "node_modules/util": { + "version": "0.12.5", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "which-typed-array": "^1.1.2" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "license": "MIT" + }, + "node_modules/util-extend": { + "version": "1.0.3", + "dev": true, + "license": "MIT" + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/uuid": { + "version": "8.3.2", + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/v8-compile-cache": { + "version": "2.3.0", + "dev": true, + "license": "MIT" + }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/v8-to-istanbul": { + "version": "9.0.1", + "dev": true, + "license": "ISC", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^1.6.0" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/v8-to-istanbul/node_modules/convert-source-map": { + "version": "1.9.0", + "dev": true, + "license": "MIT" + }, + "node_modules/varint": { + "version": "6.0.0", + "license": "MIT" + }, + "node_modules/vary": { + "version": "1.1.2", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/verror": { + "version": "1.10.0", + "engines": [ + "node >=0.6.0" + ], + "license": "MIT", + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "node_modules/verror/node_modules/core-util-is": { + "version": "1.0.2", + "license": "MIT" + }, + "node_modules/vm-browserify": { + "version": "1.1.2", + "dev": true, + "license": "MIT" + }, + "node_modules/void-elements": { + "version": "2.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/vscode-oniguruma": { + "version": "1.6.2", + "dev": true, + "license": "MIT" + }, + "node_modules/vscode-textmate": { + "version": "5.2.0", + "dev": true, + "license": "MIT" + }, + "node_modules/watchpack": { + "version": "2.4.0", + "dev": true, + "license": "MIT", + "dependencies": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/wcwidth": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "defaults": "^1.0.3" + } + }, + "node_modules/weak-lru-cache": { + "version": "1.2.2", + "dev": true, + "license": "MIT" + }, + "node_modules/web-encoding": { + "version": "1.1.5", + "license": "MIT", + "dependencies": { + "util": "^0.12.3" + }, + "optionalDependencies": { + "@zxing/text-encoding": "0.9.0" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "license": "BSD-2-Clause" + }, + "node_modules/webpack": { + "version": "5.74.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/eslint-scope": "^3.7.3", + "@types/estree": "^0.0.51", + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/wasm-edit": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1", + "acorn": "^8.7.1", + "acorn-import-assertions": "^1.7.6", + "browserslist": "^4.14.5", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.10.0", + "es-module-lexer": "^0.9.0", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.9", + "json-parse-even-better-errors": "^2.3.1", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^3.1.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.1.3", + "watchpack": "^2.4.0", + "webpack-sources": "^3.2.3" + }, + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-cli": { + "version": "4.10.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@discoveryjs/json-ext": "^0.5.0", + "@webpack-cli/configtest": "^1.2.0", + "@webpack-cli/info": "^1.5.0", + "@webpack-cli/serve": "^1.7.0", + "colorette": "^2.0.14", + "commander": "^7.0.0", + "cross-spawn": "^7.0.3", + "fastest-levenshtein": "^1.0.12", + "import-local": "^3.0.2", + "interpret": "^2.2.0", + "rechoir": "^0.7.0", + "webpack-merge": "^5.7.3" + }, + "bin": { + "webpack-cli": "bin/cli.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "4.x.x || 5.x.x" + }, + "peerDependenciesMeta": { + "@webpack-cli/generators": { + "optional": true + }, + "@webpack-cli/migrate": { + "optional": true + }, + "webpack-bundle-analyzer": { + "optional": true + }, + "webpack-dev-server": { + "optional": true + } + } + }, + "node_modules/webpack-cli/node_modules/commander": { + "version": "7.2.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/webpack-merge": { + "version": "5.8.0", + "dev": true, + "license": "MIT", + "dependencies": { + "clone-deep": "^4.0.1", + "wildcard": "^2.0.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/webpack-sources": { + "version": "3.2.3", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/webpack/node_modules/events": { + "version": "3.3.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/webpack/node_modules/schema-utils": { + "version": "3.1.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "license": "MIT", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/which": { + "version": "1.3.1", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "license": "MIT", + "dependencies": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-collection": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "is-map": "^2.0.1", + "is-set": "^2.0.1", + "is-weakmap": "^2.0.1", + "is-weakset": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-module": { + "version": "2.0.0", + "dev": true, + "license": "ISC" + }, + "node_modules/which-typed-array": { + "version": "1.1.8", + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "es-abstract": "^1.20.0", + "for-each": "^0.3.3", + "has-tostringtag": "^1.0.0", + "is-typed-array": "^1.1.9" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/wildcard": { + "version": "2.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/winston": { + "version": "3.8.2", + "license": "MIT", + "dependencies": { + "@colors/colors": "1.5.0", + "@dabh/diagnostics": "^2.0.2", + "async": "^3.2.3", + "is-stream": "^2.0.0", + "logform": "^2.4.0", + "one-time": "^1.0.0", + "readable-stream": "^3.4.0", + "safe-stable-stringify": "^2.3.1", + "stack-trace": "0.0.x", + "triple-beam": "^1.3.0", + "winston-transport": "^4.5.0" + }, + "engines": { + "node": ">= 12.0.0" + } + }, + "node_modules/winston-daily-rotate-file": { + "version": "4.7.1", + "license": "MIT", + "dependencies": { + "file-stream-rotator": "^0.6.1", + "object-hash": "^2.0.1", + "triple-beam": "^1.3.0", + "winston-transport": "^4.4.0" + }, + "engines": { + "node": ">=8" + }, + "peerDependencies": { + "winston": "^3" + } + }, + "node_modules/winston-transport": { + "version": "4.5.0", + "license": "MIT", + "dependencies": { + "logform": "^2.3.2", + "readable-stream": "^3.6.0", + "triple-beam": "^1.3.0" + }, + "engines": { + "node": ">= 6.4.0" + } + }, + "node_modules/winston-transport/node_modules/readable-stream": { + "version": "3.6.0", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/winston/node_modules/readable-stream": { + "version": "3.6.0", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/word-wrap": { + "version": "1.2.3", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wordwrap": { + "version": "1.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/emoji-regex": { + "version": "8.0.0", + "license": "MIT" + }, + "node_modules/wrap-ansi/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/string-width": { + "version": "4.2.3", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "dev": true, + "license": "ISC" + }, + "node_modules/write": { + "version": "0.2.1", + "dev": true, + "license": "MIT", + "dependencies": { + "mkdirp": "^0.5.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/write-file-atomic": { + "version": "3.0.3", + "dev": true, + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + }, + "node_modules/ws": { + "version": "7.5.9", + "license": "MIT", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xml2js": { + "version": "0.4.23", + "license": "MIT", + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/xmlbuilder": { + "version": "11.0.1", + "license": "MIT", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/xor-distance": { + "version": "2.0.0", + "license": "MIT" + }, + "node_modules/xsalsa20": { + "version": "1.2.0", + "license": "MIT" + }, + "node_modules/xtend": { + "version": "4.0.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yaml": { + "version": "2.1.3", + "dev": true, + "license": "ISC", + "engines": { + "node": ">= 14" + } + }, + "node_modules/yargs": { + "version": "16.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-parser": { + "version": "20.2.9", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs/node_modules/emoji-regex": { + "version": "8.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/yargs/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/string-width": { + "version": "4.2.3", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yn": { + "version": "3.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "packages/block": { + "name": "@ethereumjs/block", + "version": "4.2.2", + "license": "MPL-2.0", + "dependencies": { + "@ethereumjs/common": "^3.1.2", + "@ethereumjs/rlp": "^4.0.1", + "@ethereumjs/trie": "^5.0.5", + "@ethereumjs/tx": "^4.1.2", + "@ethereumjs/util": "^8.0.6", + "ethereum-cryptography": "^2.0.0" + }, + "devDependencies": { + "c-kzg": "^2.0.4", + "testdouble": "^3.17.2" + }, + "engines": { + "node": ">=16" + } + }, + "packages/blockchain": { + "name": "@ethereumjs/blockchain", + "version": "6.2.2", + "license": "MPL-2.0", + "dependencies": { + "@ethereumjs/block": "^4.2.2", + "@ethereumjs/common": "^3.1.2", + "@ethereumjs/ethash": "^2.0.5", + "@ethereumjs/rlp": "^4.0.1", + "@ethereumjs/trie": "^5.0.5", + "@ethereumjs/tx": "^4.1.2", + "@ethereumjs/util": "^8.0.6", + "debug": "^4.3.3", + "ethereum-cryptography": "^2.0.0", + "level": "^8.0.0", + "lru-cache": "^7.18.3" + }, + "devDependencies": { + "@types/async": "^2.4.1", + "@types/level-errors": "^3.0.0" + }, + "engines": { + "node": ">=16" + } + }, + "packages/client": { + "name": "@ethereumjs/client", + "version": "0.7.1", + "hasInstallScript": true, + "license": "MPL-2.0", + "dependencies": { + "@chainsafe/libp2p-noise": "^4.1.1", + "@ethereumjs/block": "4.2.2", + "@ethereumjs/blockchain": "6.2.2", + "@ethereumjs/common": "3.1.2", + "@ethereumjs/devp2p": "5.1.2", + "@ethereumjs/ethash": "2.0.5", + "@ethereumjs/evm": "1.3.2", + "@ethereumjs/rlp": "4.0.1", + "@ethereumjs/statemanager": "1.0.5", + "@ethereumjs/trie": "5.0.5", + "@ethereumjs/tx": "4.1.2", + "@ethereumjs/util": "8.0.6", + "@ethereumjs/vm": "6.4.2", + "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", + "debug": "^4.3.3", + "ethereum-cryptography": "^2.0.0", + "fs-extra": "^10.1.0", + "it-pipe": "^1.1.0", + "jayson": "^4.0.0", + "jwt-simple": "^0.5.6", + "level": "^8.0.0", + "libp2p": "^0.30.7", + "libp2p-bootstrap": "^0.14.0", + "libp2p-interfaces": "^1.2.0", + "libp2p-kad-dht": "^0.20.6", + "libp2p-mplex": "^0.10.2", + "libp2p-tcp": "^0.15.3", + "libp2p-websockets": "^0.15.1", + "memory-level": "^1.0.0", + "multiaddr": "^10.0.1", + "peer-id": "^0.14.3", + "qheap": "^1.4.0", + "winston": "^3.3.3", + "winston-daily-rotate-file": "^4.5.5", + "yargs": "^17.7.1" + }, + "bin": { + "ethereumjs": "dist/bin/cli.js" + }, + "devDependencies": { + "@types/body-parser": "^1.19.2", + "@types/connect": "^3.4.35", + "@types/fs-extra": "^9.0.13", + "@types/jwt-simple": "^0.5.33", + "@types/yargs": "^17.0.24", + "constants-browserify": "^1.0.0", + "crypto-browserify": "^3.12.0", + "file-replace-loader": "^1.2.0", + "it-pair": "^1.0.0", + "it-pushable": "^1.4.2", + "os-browserify": "^0.3.0", + "pino": "^5.8.0", + "process": "^0.11.10", + "stream-browserify": "^3.0.0", + "supertest": "^6.1.3", + "superwstest": "^2.0.1", + "testdouble": "^3.16.6", + "testdouble-timers": "^0.1.1", + "util": "^0.12.4", + "webpack": "^5.55.1", + "webpack-cli": "^4.8.0" + }, + "engines": { + "node": ">=16" + } + }, + "packages/client/node_modules/cliui": { + "version": "8.0.1", + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "packages/client/node_modules/emoji-regex": { + "version": "8.0.0", + "license": "MIT" + }, + "packages/client/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "packages/client/node_modules/string-width": { + "version": "4.2.3", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "packages/client/node_modules/yargs": { + "version": "17.7.1", + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "packages/client/node_modules/yargs-parser": { + "version": "21.1.1", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "packages/common": { + "name": "@ethereumjs/common", + "version": "3.1.2", + "license": "MIT", + "dependencies": { + "@ethereumjs/util": "^8.0.6", + "crc-32": "^1.2.0" + } + }, + "packages/devp2p": { + "name": "@ethereumjs/devp2p", + "version": "5.1.2", + "license": "MIT", + "dependencies": { + "@ethereumjs/common": "^3.1.2", + "@ethereumjs/rlp": "^4.0.1", + "@ethereumjs/util": "^8.0.6", + "@scure/base": "1.1.1", + "@types/k-bucket": "^5.0.0", + "debug": "^4.3.3", + "ethereum-cryptography": "^2.0.0", + "k-bucket": "^5.0.0", + "lru-cache": "^7.18.3", + "ms": "^0.7.1", + "multiaddr": "^10.0.1", + "scanf": "^1.1.2", + "snappyjs": "^0.6.1" + }, + "devDependencies": { + "@ethereumjs/block": "^4.2.2", + "@ethereumjs/tx": "^4.1.2", + "@types/chalk": "^2.2.0", + "@types/debug": "^4.1.4", + "@types/ip": "^1.1.0", + "@types/ms": "^0.7.30", + "chalk": "^2.4.2", + "testdouble": "^3.8.2" + }, + "engines": { + "node": ">=16" + } + }, + "packages/devp2p/node_modules/ansi-styles": { + "version": "3.2.1", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "packages/devp2p/node_modules/chalk": { + "version": "2.4.2", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "packages/devp2p/node_modules/color-convert": { + "version": "1.9.3", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "1.1.3" + } + }, + "packages/devp2p/node_modules/color-name": { + "version": "1.1.3", + "dev": true, + "license": "MIT" + }, + "packages/devp2p/node_modules/has-flag": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "packages/devp2p/node_modules/supports-color": { + "version": "5.5.0", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "packages/ethash": { + "name": "@ethereumjs/ethash", + "version": "2.0.5", + "license": "MPL-2.0", + "dependencies": { + "@ethereumjs/block": "^4.2.2", + "@ethereumjs/rlp": "^4.0.1", + "@ethereumjs/util": "^8.0.6", + "bigint-crypto-utils": "^3.2.2", + "ethereum-cryptography": "^2.0.0" + }, + "devDependencies": { + "@ethereumjs/common": "^3.1.2" + }, + "engines": { + "node": ">=16" + } + }, + "packages/evm": { + "name": "@ethereumjs/evm", + "version": "1.3.2", + "license": "MPL-2.0", + "dependencies": { + "@ethereumjs/common": "^3.1.2", + "@ethereumjs/tx": "^4.1.2", + "@ethereumjs/util": "^8.0.6", + "debug": "^4.3.3", + "ethereum-cryptography": "^2.0.0", + "mcl-wasm": "^0.7.1", + "rustbn.js": "~0.2.0" + }, + "devDependencies": { + "@ethereumjs/statemanager": "^1.0.5", + "@ethersproject/abi": "^5.0.12", + "@types/benchmark": "^1.0.33", + "@types/core-js": "^2.5.0", + "@types/minimist": "^1.2.2", + "@types/node-dir": "^0.0.34", + "benchmark": "^2.1.4", + "c-kzg": "^2.0.4", + "level": "^8.0.0", + "memory-level": "^1.0.0", + "minimist": "^1.2.5", + "node-dir": "^0.1.17", + "solc": "^0.8.1" + }, + "engines": { + "node": ">=16" + } + }, + "packages/rlp": { + "name": "@ethereumjs/rlp", + "version": "4.0.1", + "license": "MPL-2.0", + "bin": { + "rlp": "bin/rlp" + }, + "engines": { + "node": ">=16" + } + }, + "packages/statemanager": { + "name": "@ethereumjs/statemanager", + "version": "1.0.5", + "license": "MPL-2.0", + "dependencies": { + "@ethereumjs/common": "^3.1.2", + "@ethereumjs/rlp": "^4.0.1", + "debug": "^4.3.3", + "ethereum-cryptography": "^2.0.0", + "ethers": "^5.7.1", + "js-sdsl": "^4.1.4", + "lru-cache": "^7.18.3" + }, + "devDependencies": { + "@ethereumjs/block": "^4.2.2", + "@ethereumjs/trie": "^5.0.5", + "@ethereumjs/util": "^8.0.6", + "@types/node": "^16.11.7", + "@types/tape": "^4.13.2", + "debug": "^4.3.3", + "eslint": "^8.0.0", + "ethereum-cryptography": "^2.0.0", + "functional-red-black-tree": "^1.0.1", + "karma": "^6.3.2", + "karma-chrome-launcher": "^3.1.0", + "karma-firefox-launcher": "^2.1.0", + "karma-tap": "^4.2.0", + "karma-typescript": "^5.5.3", + "nyc": "^15.1.0", + "standard": "^10.0.0", + "tape": "^5.3.1", + "ts-node": "^10.2.1", + "typescript": "^4.4.2" + } + }, + "packages/trie": { + "name": "@ethereumjs/trie", + "version": "5.0.5", + "license": "MPL-2.0", + "dependencies": { + "@ethereumjs/rlp": "^4.0.1", + "@ethereumjs/util": "^8.0.6", + "@types/readable-stream": "^2.3.13", + "ethereum-cryptography": "^2.0.0", + "lru-cache": "^7.18.3", + "readable-stream": "^3.6.0" + }, + "devDependencies": { + "@types/benchmark": "^1.0.33", + "0x": "^4.9.1", + "abstract-level": "^1.0.3", + "level": "^8.0.0", + "level-legacy": "npm:level@^7.0.0", + "level-mem": "^6.0.1", + "levelup": "^5.1.1", + "lmdb": "^2.5.3", + "memory-level": "^1.0.0", + "micro-bmark": "0.2.0" + }, + "engines": { + "node": ">=16" + } + }, + "packages/trie/node_modules/readable-stream": { + "version": "3.6.0", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "packages/tx": { + "name": "@ethereumjs/tx", + "version": "4.1.2", + "license": "MPL-2.0", + "dependencies": { + "@chainsafe/ssz": "^0.11.1", + "@ethereumjs/common": "^3.1.2", + "@ethereumjs/rlp": "^4.0.1", + "@ethereumjs/util": "^8.0.6", + "ethereum-cryptography": "^2.0.0" + }, + "devDependencies": { + "@types/minimist": "^1.2.0", + "@types/node-dir": "^0.0.34", + "minimist": "^1.2.0", + "node-dir": "^0.1.16", + "testdouble": "^3.17.2" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "c-kzg": "^2.0.4" + }, + "peerDependenciesMeta": { + "c-kzg": { + "optional": true + } + } + }, + "packages/util": { + "name": "@ethereumjs/util", + "version": "8.0.6", + "license": "MPL-2.0", + "dependencies": { + "@chainsafe/ssz": "^0.11.1", + "@ethereumjs/rlp": "^4.0.1", + "ethereum-cryptography": "^2.0.0" + }, + "devDependencies": { + "@types/bn.js": "^5.1.0", + "@types/secp256k1": "^4.0.1" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "c-kzg": "^2.0.4" + }, + "peerDependenciesMeta": { + "c-kzg": { + "optional": true + } + } + }, + "packages/vm": { + "name": "@ethereumjs/vm", + "version": "6.4.2", + "license": "MPL-2.0", + "dependencies": { + "@ethereumjs/block": "^4.2.2", + "@ethereumjs/blockchain": "^6.2.2", + "@ethereumjs/common": "^3.1.2", + "@ethereumjs/evm": "^1.3.2", + "@ethereumjs/rlp": "^4.0.1", + "@ethereumjs/statemanager": "^1.0.5", + "@ethereumjs/trie": "^5.0.5", + "@ethereumjs/tx": "^4.1.2", + "@ethereumjs/util": "^8.0.6", + "debug": "^4.3.3", + "ethereum-cryptography": "^2.0.0", + "mcl-wasm": "^0.7.1", + "rustbn.js": "~0.2.0" + }, + "devDependencies": { + "@ethersproject/abi": "^5.0.12", + "@types/benchmark": "^1.0.33", + "@types/core-js": "^2.5.0", + "@types/minimist": "^1.2.2", + "@types/node-dir": "^0.0.34", + "benchmark": "^2.1.4", + "c-kzg": "^2.0.4", + "minimist": "^1.2.5", + "node-dir": "^0.1.17", + "nyc": "^15.1.0", + "prettier": "^2.0.5", + "solc": "^0.8.1", + "standard": "^10.0.0", + "tape": "^5.3.1", + "ts-node": "^10.2.1", + "typedoc": "^0.22.4", + "typescript": "^4.4.2" + }, + "engines": { + "node": ">=16" + } + }, + "packages/vm/node_modules/brace-expansion": { + "version": "2.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "packages/vm/node_modules/glob": { + "version": "8.0.3", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "packages/vm/node_modules/minimatch": { + "version": "5.1.0", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "packages/vm/node_modules/typedoc": { + "version": "0.22.18", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "glob": "^8.0.3", + "lunr": "^2.3.9", + "marked": "^4.0.16", + "minimatch": "^5.1.0", + "shiki": "^0.10.1" + }, + "bin": { + "typedoc": "bin/typedoc" + }, + "engines": { + "node": ">= 12.10.0" + }, + "peerDependencies": { + "typescript": "4.0.x || 4.1.x || 4.2.x || 4.3.x || 4.4.x || 4.5.x || 4.6.x || 4.7.x" + } + } + }, + "dependencies": { + "@ampproject/remapping": { + "version": "2.2.0", + "dev": true, + "requires": { + "@jridgewell/gen-mapping": "^0.1.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "@babel/code-frame": { + "version": "7.12.11", + "dev": true, + "requires": { + "@babel/highlight": "^7.10.4" + } + }, + "@babel/compat-data": { + "version": "7.19.4", + "dev": true + }, + "@babel/core": { + "version": "7.19.6", + "dev": true, + "requires": { + "@ampproject/remapping": "^2.1.0", + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.19.6", + "@babel/helper-compilation-targets": "^7.19.3", + "@babel/helper-module-transforms": "^7.19.6", + "@babel/helpers": "^7.19.4", + "@babel/parser": "^7.19.6", + "@babel/template": "^7.18.10", + "@babel/traverse": "^7.19.6", + "@babel/types": "^7.19.4", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.1", + "semver": "^6.3.0" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.18.6", + "dev": true, + "requires": { + "@babel/highlight": "^7.18.6" + } + }, + "convert-source-map": { + "version": "1.9.0", + "dev": true + }, + "semver": { + "version": "6.3.0", + "dev": true + } + } + }, + "@babel/generator": { + "version": "7.19.6", + "dev": true, + "requires": { + "@babel/types": "^7.19.4", + "@jridgewell/gen-mapping": "^0.3.2", + "jsesc": "^2.5.1" + }, + "dependencies": { + "@jridgewell/gen-mapping": { + "version": "0.3.2", + "dev": true, + "requires": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + } + } + } + }, + "@babel/helper-annotate-as-pure": { + "version": "7.18.6", + "dev": true, + "requires": { + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.18.9", + "dev": true, + "requires": { + "@babel/helper-explode-assignable-expression": "^7.18.6", + "@babel/types": "^7.18.9" + } + }, + "@babel/helper-compilation-targets": { + "version": "7.19.3", + "dev": true, + "requires": { + "@babel/compat-data": "^7.19.3", + "@babel/helper-validator-option": "^7.18.6", + "browserslist": "^4.21.3", + "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "dev": true + } + } + }, + "@babel/helper-create-class-features-plugin": { + "version": "7.19.0", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.19.0", + "@babel/helper-member-expression-to-functions": "^7.18.9", + "@babel/helper-optimise-call-expression": "^7.18.6", + "@babel/helper-replace-supers": "^7.18.9", + "@babel/helper-split-export-declaration": "^7.18.6" + } + }, + "@babel/helper-create-regexp-features-plugin": { + "version": "7.19.0", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "regexpu-core": "^5.1.0" + } + }, + "@babel/helper-define-polyfill-provider": { + "version": "0.3.3", + "dev": true, + "requires": { + "@babel/helper-compilation-targets": "^7.17.7", + "@babel/helper-plugin-utils": "^7.16.7", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2", + "semver": "^6.1.2" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "dev": true + } + } + }, + "@babel/helper-environment-visitor": { + "version": "7.18.9", + "dev": true + }, + "@babel/helper-explode-assignable-expression": { + "version": "7.18.6", + "dev": true, + "requires": { + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-function-name": { + "version": "7.19.0", + "dev": true, + "requires": { + "@babel/template": "^7.18.10", + "@babel/types": "^7.19.0" + } + }, + "@babel/helper-hoist-variables": { + "version": "7.18.6", + "dev": true, + "requires": { + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-member-expression-to-functions": { + "version": "7.18.9", + "dev": true, + "requires": { + "@babel/types": "^7.18.9" + } + }, + "@babel/helper-module-imports": { + "version": "7.18.6", + "dev": true, + "requires": { + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-module-transforms": { + "version": "7.19.6", + "dev": true, + "requires": { + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-module-imports": "^7.18.6", + "@babel/helper-simple-access": "^7.19.4", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/helper-validator-identifier": "^7.19.1", + "@babel/template": "^7.18.10", + "@babel/traverse": "^7.19.6", + "@babel/types": "^7.19.4" + } + }, + "@babel/helper-optimise-call-expression": { + "version": "7.18.6", + "dev": true, + "requires": { + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.19.0", + "dev": true + }, + "@babel/helper-remap-async-to-generator": { + "version": "7.18.9", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-wrap-function": "^7.18.9", + "@babel/types": "^7.18.9" + } + }, + "@babel/helper-replace-supers": { + "version": "7.19.1", + "dev": true, + "requires": { + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-member-expression-to-functions": "^7.18.9", + "@babel/helper-optimise-call-expression": "^7.18.6", + "@babel/traverse": "^7.19.1", + "@babel/types": "^7.19.0" + } + }, + "@babel/helper-simple-access": { + "version": "7.19.4", + "dev": true, + "requires": { + "@babel/types": "^7.19.4" + } + }, + "@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.18.9", + "dev": true, + "requires": { + "@babel/types": "^7.18.9" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.18.6", + "dev": true, + "requires": { + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-string-parser": { + "version": "7.19.4", + "dev": true + }, + "@babel/helper-validator-identifier": { + "version": "7.19.1", + "dev": true + }, + "@babel/helper-validator-option": { + "version": "7.18.6", + "dev": true + }, + "@babel/helper-wrap-function": { + "version": "7.19.0", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.19.0", + "@babel/template": "^7.18.10", + "@babel/traverse": "^7.19.0", + "@babel/types": "^7.19.0" + } + }, + "@babel/helpers": { + "version": "7.19.4", + "dev": true, + "requires": { + "@babel/template": "^7.18.10", + "@babel/traverse": "^7.19.4", + "@babel/types": "^7.19.4" + } + }, + "@babel/highlight": { + "version": "7.18.6", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.18.6", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "@babel/parser": { + "version": "7.19.6", + "dev": true + }, + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.18.6", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.18.9", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.18.9", + "@babel/plugin-proposal-optional-chaining": "^7.18.9" + } + }, + "@babel/plugin-proposal-async-generator-functions": { + "version": "7.19.1", + "dev": true, + "requires": { + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-plugin-utils": "^7.19.0", + "@babel/helper-remap-async-to-generator": "^7.18.9", + "@babel/plugin-syntax-async-generators": "^7.8.4" + } + }, + "@babel/plugin-proposal-class-properties": { + "version": "7.18.6", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-proposal-class-static-block": { + "version": "7.18.6", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-class-static-block": "^7.14.5" + } + }, + "@babel/plugin-proposal-dynamic-import": { + "version": "7.18.6", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-dynamic-import": "^7.8.3" + } + }, + "@babel/plugin-proposal-export-namespace-from": { + "version": "7.18.9", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + } + }, + "@babel/plugin-proposal-json-strings": { + "version": "7.18.6", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-json-strings": "^7.8.3" + } + }, + "@babel/plugin-proposal-logical-assignment-operators": { + "version": "7.18.9", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + } + }, + "@babel/plugin-proposal-nullish-coalescing-operator": { + "version": "7.18.6", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + } + }, + "@babel/plugin-proposal-numeric-separator": { + "version": "7.18.6", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + } + }, + "@babel/plugin-proposal-object-rest-spread": { + "version": "7.19.4", + "dev": true, + "requires": { + "@babel/compat-data": "^7.19.4", + "@babel/helper-compilation-targets": "^7.19.3", + "@babel/helper-plugin-utils": "^7.19.0", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.18.8" + } + }, + "@babel/plugin-proposal-optional-catch-binding": { + "version": "7.18.6", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" + } + }, + "@babel/plugin-proposal-optional-chaining": { + "version": "7.18.9", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.18.9", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" + } + }, + "@babel/plugin-proposal-private-methods": { + "version": "7.18.6", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-proposal-private-property-in-object": { + "version": "7.18.6", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-create-class-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5" + } + }, + "@babel/plugin-proposal-unicode-property-regex": { + "version": "7.18.6", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.12.13" + } + }, + "@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-export-namespace-from": { + "version": "7.8.3", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-syntax-import-assertions": { + "version": "7.18.6", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-transform-arrow-functions": { + "version": "7.18.6", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-async-to-generator": { + "version": "7.18.6", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/helper-remap-async-to-generator": "^7.18.6" + } + }, + "@babel/plugin-transform-block-scoped-functions": { + "version": "7.18.6", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-block-scoping": { + "version": "7.19.4", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.19.0" + } + }, + "@babel/plugin-transform-classes": { + "version": "7.19.0", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-compilation-targets": "^7.19.0", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.19.0", + "@babel/helper-optimise-call-expression": "^7.18.6", + "@babel/helper-plugin-utils": "^7.19.0", + "@babel/helper-replace-supers": "^7.18.9", + "@babel/helper-split-export-declaration": "^7.18.6", + "globals": "^11.1.0" + }, + "dependencies": { + "globals": { + "version": "11.12.0", + "dev": true + } + } + }, + "@babel/plugin-transform-computed-properties": { + "version": "7.18.9", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.9" + } + }, + "@babel/plugin-transform-destructuring": { + "version": "7.19.4", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.19.0" + } + }, + "@babel/plugin-transform-dotall-regex": { + "version": "7.18.6", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-duplicate-keys": { + "version": "7.18.9", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.9" + } + }, + "@babel/plugin-transform-exponentiation-operator": { + "version": "7.18.6", + "dev": true, + "requires": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-for-of": { + "version": "7.18.8", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-function-name": { + "version": "7.18.9", + "dev": true, + "requires": { + "@babel/helper-compilation-targets": "^7.18.9", + "@babel/helper-function-name": "^7.18.9", + "@babel/helper-plugin-utils": "^7.18.9" + } + }, + "@babel/plugin-transform-literals": { + "version": "7.18.9", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.9" + } + }, + "@babel/plugin-transform-member-expression-literals": { + "version": "7.18.6", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-modules-amd": { + "version": "7.19.6", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.19.6", + "@babel/helper-plugin-utils": "^7.19.0" + } + }, + "@babel/plugin-transform-modules-commonjs": { + "version": "7.19.6", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.19.6", + "@babel/helper-plugin-utils": "^7.19.0", + "@babel/helper-simple-access": "^7.19.4" + } + }, + "@babel/plugin-transform-modules-systemjs": { + "version": "7.19.6", + "dev": true, + "requires": { + "@babel/helper-hoist-variables": "^7.18.6", + "@babel/helper-module-transforms": "^7.19.6", + "@babel/helper-plugin-utils": "^7.19.0", + "@babel/helper-validator-identifier": "^7.19.1" + } + }, + "@babel/plugin-transform-modules-umd": { + "version": "7.18.6", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.19.1", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.19.0", + "@babel/helper-plugin-utils": "^7.19.0" + } + }, + "@babel/plugin-transform-new-target": { + "version": "7.18.6", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-object-super": { + "version": "7.18.6", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/helper-replace-supers": "^7.18.6" + } + }, + "@babel/plugin-transform-parameters": { + "version": "7.18.8", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-property-literals": { + "version": "7.18.6", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-regenerator": { + "version": "7.18.6", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6", + "regenerator-transform": "^0.15.0" + } + }, + "@babel/plugin-transform-reserved-words": { + "version": "7.18.6", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-shorthand-properties": { + "version": "7.18.6", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-spread": { + "version": "7.19.0", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.19.0", + "@babel/helper-skip-transparent-expression-wrappers": "^7.18.9" + } + }, + "@babel/plugin-transform-sticky-regex": { + "version": "7.18.6", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-template-literals": { + "version": "7.18.9", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.9" + } + }, + "@babel/plugin-transform-typeof-symbol": { + "version": "7.18.9", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.9" + } + }, + "@babel/plugin-transform-unicode-escapes": { + "version": "7.18.10", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.9" + } + }, + "@babel/plugin-transform-unicode-regex": { + "version": "7.18.6", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/preset-env": { + "version": "7.19.4", + "dev": true, + "requires": { + "@babel/compat-data": "^7.19.4", + "@babel/helper-compilation-targets": "^7.19.3", + "@babel/helper-plugin-utils": "^7.19.0", + "@babel/helper-validator-option": "^7.18.6", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.18.6", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.18.9", + "@babel/plugin-proposal-async-generator-functions": "^7.19.1", + "@babel/plugin-proposal-class-properties": "^7.18.6", + "@babel/plugin-proposal-class-static-block": "^7.18.6", + "@babel/plugin-proposal-dynamic-import": "^7.18.6", + "@babel/plugin-proposal-export-namespace-from": "^7.18.9", + "@babel/plugin-proposal-json-strings": "^7.18.6", + "@babel/plugin-proposal-logical-assignment-operators": "^7.18.9", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.18.6", + "@babel/plugin-proposal-numeric-separator": "^7.18.6", + "@babel/plugin-proposal-object-rest-spread": "^7.19.4", + "@babel/plugin-proposal-optional-catch-binding": "^7.18.6", + "@babel/plugin-proposal-optional-chaining": "^7.18.9", + "@babel/plugin-proposal-private-methods": "^7.18.6", + "@babel/plugin-proposal-private-property-in-object": "^7.18.6", + "@babel/plugin-proposal-unicode-property-regex": "^7.18.6", + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3", + "@babel/plugin-syntax-import-assertions": "^7.18.6", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5", + "@babel/plugin-transform-arrow-functions": "^7.18.6", + "@babel/plugin-transform-async-to-generator": "^7.18.6", + "@babel/plugin-transform-block-scoped-functions": "^7.18.6", + "@babel/plugin-transform-block-scoping": "^7.19.4", + "@babel/plugin-transform-classes": "^7.19.0", + "@babel/plugin-transform-computed-properties": "^7.18.9", + "@babel/plugin-transform-destructuring": "^7.19.4", + "@babel/plugin-transform-dotall-regex": "^7.18.6", + "@babel/plugin-transform-duplicate-keys": "^7.18.9", + "@babel/plugin-transform-exponentiation-operator": "^7.18.6", + "@babel/plugin-transform-for-of": "^7.18.8", + "@babel/plugin-transform-function-name": "^7.18.9", + "@babel/plugin-transform-literals": "^7.18.9", + "@babel/plugin-transform-member-expression-literals": "^7.18.6", + "@babel/plugin-transform-modules-amd": "^7.18.6", + "@babel/plugin-transform-modules-commonjs": "^7.18.6", + "@babel/plugin-transform-modules-systemjs": "^7.19.0", + "@babel/plugin-transform-modules-umd": "^7.18.6", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.19.1", + "@babel/plugin-transform-new-target": "^7.18.6", + "@babel/plugin-transform-object-super": "^7.18.6", + "@babel/plugin-transform-parameters": "^7.18.8", + "@babel/plugin-transform-property-literals": "^7.18.6", + "@babel/plugin-transform-regenerator": "^7.18.6", + "@babel/plugin-transform-reserved-words": "^7.18.6", + "@babel/plugin-transform-shorthand-properties": "^7.18.6", + "@babel/plugin-transform-spread": "^7.19.0", + "@babel/plugin-transform-sticky-regex": "^7.18.6", + "@babel/plugin-transform-template-literals": "^7.18.9", + "@babel/plugin-transform-typeof-symbol": "^7.18.9", + "@babel/plugin-transform-unicode-escapes": "^7.18.10", + "@babel/plugin-transform-unicode-regex": "^7.18.6", + "@babel/preset-modules": "^0.1.5", + "@babel/types": "^7.19.4", + "babel-plugin-polyfill-corejs2": "^0.3.3", + "babel-plugin-polyfill-corejs3": "^0.6.0", + "babel-plugin-polyfill-regenerator": "^0.4.1", + "core-js-compat": "^3.25.1", + "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "dev": true + } + } + }, + "@babel/preset-modules": { + "version": "0.1.5", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", + "@babel/plugin-transform-dotall-regex": "^7.4.4", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + } + }, + "@babel/runtime": { + "version": "7.19.4", + "dev": true, + "requires": { + "regenerator-runtime": "^0.13.4" + } + }, + "@babel/runtime-corejs3": { + "version": "7.19.6", + "dev": true, + "requires": { + "core-js-pure": "^3.25.1", + "regenerator-runtime": "^0.13.4" + } + }, + "@babel/template": { + "version": "7.18.10", + "dev": true, + "requires": { + "@babel/code-frame": "^7.18.6", + "@babel/parser": "^7.18.10", + "@babel/types": "^7.18.10" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.18.6", + "dev": true, + "requires": { + "@babel/highlight": "^7.18.6" + } + } + } + }, + "@babel/traverse": { + "version": "7.19.6", + "dev": true, + "requires": { + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.19.6", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.19.0", + "@babel/helper-hoist-variables": "^7.18.6", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/parser": "^7.19.6", + "@babel/types": "^7.19.4", + "debug": "^4.1.0", + "globals": "^11.1.0" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.18.6", + "dev": true, + "requires": { + "@babel/highlight": "^7.18.6" + } + }, + "globals": { + "version": "11.12.0", + "dev": true + } + } + }, + "@babel/types": { + "version": "7.19.4", + "dev": true, + "requires": { + "@babel/helper-string-parser": "^7.19.4", + "@babel/helper-validator-identifier": "^7.19.1", + "to-fast-properties": "^2.0.0" + } + }, + "@bcoe/v8-coverage": { + "version": "0.2.3", + "dev": true + }, + "@chainsafe/as-sha256": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@chainsafe/as-sha256/-/as-sha256-0.4.1.tgz", + "integrity": "sha512-IqeeGwQihK6Y2EYLFofqs2eY2ep1I2MvQXHzOAI+5iQN51OZlUkrLgyAugu2x86xZewDk5xas7lNczkzFzF62w==" + }, + "@chainsafe/libp2p-noise": { + "version": "4.1.2", + "requires": { + "@stablelib/chacha20poly1305": "^1.0.1", + "@stablelib/hkdf": "^1.0.1", + "@stablelib/sha256": "^1.0.1", + "@stablelib/x25519": "^1.0.1", + "debug": "^4.3.1", + "it-buffer": "^0.1.3", + "it-length-prefixed": "^5.0.3", + "it-pair": "^1.0.0", + "it-pb-rpc": "^0.1.11", + "it-pipe": "^1.1.0", + "libp2p-crypto": "^0.19.7", + "peer-id": "^0.15.3", + "protobufjs": "^6.11.2", + "uint8arrays": "^3.0.0" + }, + "dependencies": { + "err-code": { + "version": "3.0.1" + }, + "peer-id": { + "version": "0.15.4", + "requires": { + "class-is": "^1.1.0", + "libp2p-crypto": "^0.20.0", + "minimist": "^1.2.5", + "multiformats": "^9.4.5", + "protobufjs": "^6.10.2", + "uint8arrays": "^3.0.0" + }, + "dependencies": { + "libp2p-crypto": { + "version": "0.20.0", + "requires": { + "err-code": "^3.0.1", + "iso-random-stream": "^2.0.0", + "keypair": "^1.0.4", + "multiformats": "^9.4.5", + "noble-ed25519": "^1.2.6", + "noble-secp256k1": "^1.2.10", + "node-forge": "^0.10.0", + "pem-jwk": "^2.0.0", + "protobufjs": "^6.11.2", + "uint8arrays": "^3.0.0", + "ursa-optional": "^0.10.1" + } + } + } + } + } + }, + "@chainsafe/persistent-merkle-tree": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/@chainsafe/persistent-merkle-tree/-/persistent-merkle-tree-0.6.1.tgz", + "integrity": "sha512-gcENLemRR13+1MED2NeZBMA7FRS0xQPM7L2vhMqvKkjqtFT4YfjSVADq5U0iLuQLhFUJEMVuA8fbv5v+TN6O9A==", + "requires": { + "@chainsafe/as-sha256": "^0.4.1", + "@noble/hashes": "^1.3.0" + } + }, + "@chainsafe/ssz": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/@chainsafe/ssz/-/ssz-0.11.1.tgz", + "integrity": "sha512-cB8dBkgGN6ZoeOKuk+rIRHKN0L5i9JLGeC0Lui71QX0TuLcQKwgbfkUexpyJxnGFatWf8yeJxlOjozMn/OTP0g==", + "requires": { + "@chainsafe/as-sha256": "^0.4.1", + "@chainsafe/persistent-merkle-tree": "^0.6.1" + } + }, + "@colors/colors": { + "version": "1.5.0" + }, + "@cspotcode/source-map-support": { + "version": "0.8.1", + "dev": true, + "requires": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "dependencies": { + "@jridgewell/trace-mapping": { + "version": "0.3.9", + "dev": true, + "requires": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + } + } + }, + "@dabh/diagnostics": { + "version": "2.0.3", + "requires": { + "colorspace": "1.1.x", + "enabled": "2.0.x", + "kuler": "^2.0.0" + } + }, + "@discoveryjs/json-ext": { + "version": "0.5.7", + "dev": true + }, + "@eslint/eslintrc": { + "version": "1.3.3", + "dev": true, + "requires": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.4.0", + "globals": "^13.15.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + } + }, + "@ethereumjs/block": { + "version": "file:packages/block", + "requires": { + "@ethereumjs/common": "^3.1.2", + "@ethereumjs/rlp": "^4.0.1", + "@ethereumjs/trie": "^5.0.5", + "@ethereumjs/tx": "^4.1.2", + "@ethereumjs/util": "^8.0.6", + "c-kzg": "^2.0.4", + "ethereum-cryptography": "^2.0.0", + "testdouble": "^3.17.2" + } + }, + "@ethereumjs/blockchain": { + "version": "file:packages/blockchain", + "requires": { + "@ethereumjs/block": "^4.2.2", + "@ethereumjs/common": "^3.1.2", + "@ethereumjs/ethash": "^2.0.5", + "@ethereumjs/rlp": "^4.0.1", + "@ethereumjs/trie": "^5.0.5", + "@ethereumjs/tx": "^4.1.2", + "@ethereumjs/util": "^8.0.6", + "@types/async": "^2.4.1", + "@types/level-errors": "^3.0.0", + "debug": "^4.3.3", + "ethereum-cryptography": "^2.0.0", + "level": "^8.0.0", + "lru-cache": "^7.18.3" + } + }, + "@ethereumjs/client": { + "version": "file:packages/client", + "requires": { + "@chainsafe/libp2p-noise": "^4.1.1", + "@ethereumjs/block": "4.2.2", + "@ethereumjs/blockchain": "6.2.2", + "@ethereumjs/common": "3.1.2", + "@ethereumjs/devp2p": "5.1.2", + "@ethereumjs/ethash": "2.0.5", + "@ethereumjs/evm": "1.3.2", + "@ethereumjs/rlp": "4.0.1", + "@ethereumjs/statemanager": "1.0.5", + "@ethereumjs/trie": "5.0.5", + "@ethereumjs/tx": "4.1.2", + "@ethereumjs/util": "8.0.6", + "@ethereumjs/vm": "6.4.2", + "@types/body-parser": "^1.19.2", + "@types/connect": "^3.4.35", + "@types/fs-extra": "^9.0.13", + "@types/jwt-simple": "^0.5.33", + "@types/yargs": "^17.0.24", + "abstract-level": "^1.0.3", + "body-parser": "^1.19.2", + "c-kzg": "^2.0.4", + "chalk": "^4.1.2", + "connect": "^3.7.0", + "constants-browserify": "^1.0.0", + "cors": "^2.8.5", + "crypto-browserify": "^3.12.0", + "debug": "^4.3.3", + "ethereum-cryptography": "^2.0.0", + "file-replace-loader": "^1.2.0", + "fs-extra": "^10.1.0", + "it-pair": "^1.0.0", + "it-pipe": "^1.1.0", + "it-pushable": "^1.4.2", + "jayson": "^4.0.0", + "jwt-simple": "^0.5.6", + "level": "^8.0.0", + "libp2p": "^0.30.7", + "libp2p-bootstrap": "^0.14.0", + "libp2p-interfaces": "^1.2.0", + "libp2p-kad-dht": "^0.20.6", + "libp2p-mplex": "^0.10.2", + "libp2p-tcp": "^0.15.3", + "libp2p-websockets": "^0.15.1", + "memory-level": "^1.0.0", + "multiaddr": "^10.0.1", + "os-browserify": "^0.3.0", + "peer-id": "^0.14.3", + "pino": "^5.8.0", + "process": "^0.11.10", + "qheap": "^1.4.0", + "stream-browserify": "^3.0.0", + "supertest": "^6.1.3", + "superwstest": "^2.0.1", + "testdouble": "^3.16.6", + "testdouble-timers": "^0.1.1", + "util": "^0.12.4", + "webpack": "^5.55.1", + "webpack-cli": "^4.8.0", + "winston": "^3.3.3", + "winston-daily-rotate-file": "^4.5.5", + "yargs": "^17.7.1" + }, + "dependencies": { + "cliui": { + "version": "8.0.1", + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + } + }, + "emoji-regex": { + "version": "8.0.0" + }, + "is-fullwidth-code-point": { + "version": "3.0.0" + }, + "string-width": { + "version": "4.2.3", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "yargs": { + "version": "17.7.1", + "requires": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + } + }, + "yargs-parser": { + "version": "21.1.1" + } + } + }, + "@ethereumjs/common": { + "version": "file:packages/common", + "requires": { + "@ethereumjs/util": "^8.0.6", + "crc-32": "^1.2.0" + } + }, + "@ethereumjs/devp2p": { + "version": "file:packages/devp2p", + "requires": { + "@ethereumjs/block": "^4.2.2", + "@ethereumjs/common": "^3.1.2", + "@ethereumjs/rlp": "^4.0.1", + "@ethereumjs/tx": "^4.1.2", + "@ethereumjs/util": "^8.0.6", + "@scure/base": "1.1.1", + "@types/chalk": "^2.2.0", + "@types/debug": "^4.1.4", + "@types/ip": "^1.1.0", + "@types/k-bucket": "^5.0.0", + "@types/ms": "^0.7.30", + "chalk": "^2.4.2", + "debug": "^4.3.3", + "ethereum-cryptography": "^2.0.0", + "k-bucket": "^5.0.0", + "lru-cache": "^7.18.3", + "ms": "^0.7.1", + "multiaddr": "^10.0.1", + "scanf": "^1.1.2", + "snappyjs": "^0.6.1", + "testdouble": "^3.8.2" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "@ethereumjs/ethash": { + "version": "file:packages/ethash", + "requires": { + "@ethereumjs/block": "^4.2.2", + "@ethereumjs/common": "^3.1.2", + "@ethereumjs/rlp": "^4.0.1", + "@ethereumjs/util": "^8.0.6", + "bigint-crypto-utils": "^3.2.2", + "ethereum-cryptography": "^2.0.0" + } + }, + "@ethereumjs/evm": { + "version": "file:packages/evm", + "requires": { + "@ethereumjs/common": "^3.1.2", + "@ethereumjs/statemanager": "^1.0.5", + "@ethereumjs/tx": "^4.1.2", + "@ethereumjs/util": "^8.0.6", + "@ethersproject/abi": "^5.0.12", + "@types/benchmark": "^1.0.33", + "@types/core-js": "^2.5.0", + "@types/minimist": "^1.2.2", + "@types/node-dir": "^0.0.34", + "benchmark": "^2.1.4", + "c-kzg": "^2.0.4", + "debug": "^4.3.3", + "ethereum-cryptography": "^2.0.0", + "level": "^8.0.0", + "mcl-wasm": "^0.7.1", + "memory-level": "^1.0.0", + "minimist": "^1.2.5", + "node-dir": "^0.1.17", + "rustbn.js": "~0.2.0", + "solc": "^0.8.1" + } + }, + "@ethereumjs/rlp": { + "version": "file:packages/rlp" + }, + "@ethereumjs/statemanager": { + "version": "file:packages/statemanager", + "requires": { + "@ethereumjs/block": "^4.2.2", + "@ethereumjs/common": "^3.1.2", + "@ethereumjs/rlp": "^4.0.1", + "@ethereumjs/trie": "^5.0.5", + "@ethereumjs/util": "^8.0.6", + "@types/node": "^16.11.7", + "@types/tape": "^4.13.2", + "debug": "^4.3.3", + "eslint": "^8.0.0", + "ethereum-cryptography": "^2.0.0", + "ethers": "^5.7.1", + "functional-red-black-tree": "^1.0.1", + "js-sdsl": "^4.1.4", + "karma": "^6.3.2", + "karma-chrome-launcher": "^3.1.0", + "karma-firefox-launcher": "^2.1.0", + "karma-tap": "^4.2.0", + "karma-typescript": "^5.5.3", + "lru-cache": "^7.18.3", + "nyc": "^15.1.0", + "standard": "^10.0.0", + "tape": "^5.3.1", + "ts-node": "^10.2.1", + "typescript": "^4.4.2" + } + }, + "@ethereumjs/trie": { + "version": "file:packages/trie", + "requires": { + "@ethereumjs/rlp": "^4.0.1", + "@ethereumjs/util": "^8.0.6", + "@types/benchmark": "^1.0.33", + "@types/readable-stream": "^2.3.13", + "0x": "^4.9.1", + "abstract-level": "^1.0.3", + "ethereum-cryptography": "^2.0.0", + "level": "^8.0.0", + "level-legacy": "npm:level@^7.0.0", + "level-mem": "^6.0.1", + "levelup": "^5.1.1", + "lmdb": "^2.5.3", + "lru-cache": "^7.18.3", + "memory-level": "^1.0.0", + "micro-bmark": "0.2.0", + "readable-stream": "^3.6.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "@ethereumjs/tx": { + "version": "file:packages/tx", + "requires": { + "@chainsafe/ssz": "^0.11.1", + "@ethereumjs/common": "^3.1.2", + "@ethereumjs/rlp": "^4.0.1", + "@ethereumjs/util": "^8.0.6", + "@types/minimist": "^1.2.0", + "@types/node-dir": "^0.0.34", + "ethereum-cryptography": "^2.0.0", + "minimist": "^1.2.0", + "node-dir": "^0.1.16", + "testdouble": "^3.17.2" + } + }, + "@ethereumjs/util": { + "version": "file:packages/util", + "requires": { + "@chainsafe/ssz": "^0.11.1", + "@ethereumjs/rlp": "^4.0.1", + "@types/bn.js": "^5.1.0", + "@types/secp256k1": "^4.0.1", + "ethereum-cryptography": "^2.0.0" + } + }, + "@ethereumjs/vm": { + "version": "file:packages/vm", + "requires": { + "@ethereumjs/block": "^4.2.2", + "@ethereumjs/blockchain": "^6.2.2", + "@ethereumjs/common": "^3.1.2", + "@ethereumjs/evm": "^1.3.2", + "@ethereumjs/rlp": "^4.0.1", + "@ethereumjs/statemanager": "^1.0.5", + "@ethereumjs/trie": "^5.0.5", + "@ethereumjs/tx": "^4.1.2", + "@ethereumjs/util": "^8.0.6", + "@ethersproject/abi": "^5.0.12", + "@types/benchmark": "^1.0.33", + "@types/core-js": "^2.5.0", + "@types/minimist": "^1.2.2", + "@types/node-dir": "^0.0.34", + "benchmark": "^2.1.4", + "c-kzg": "^2.0.4", + "debug": "^4.3.3", + "ethereum-cryptography": "^2.0.0", + "mcl-wasm": "^0.7.1", + "minimist": "^1.2.5", + "node-dir": "^0.1.17", + "nyc": "^15.1.0", + "prettier": "^2.0.5", + "rustbn.js": "~0.2.0", + "solc": "^0.8.1", + "standard": "^10.0.0", + "tape": "^5.3.1", + "ts-node": "^10.2.1", + "typedoc": "^0.22.4", + "typescript": "^4.4.2" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "glob": { + "version": "8.0.3", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + } + }, + "minimatch": { + "version": "5.1.0", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + }, + "typedoc": { + "version": "0.22.18", + "dev": true, + "requires": { + "glob": "^8.0.3", + "lunr": "^2.3.9", + "marked": "^4.0.16", + "minimatch": "^5.1.0", + "shiki": "^0.10.1" + } + } + } + }, + "@ethersproject/abi": { + "version": "5.7.0", + "requires": { + "@ethersproject/address": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/constants": "^5.7.0", + "@ethersproject/hash": "^5.7.0", + "@ethersproject/keccak256": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/strings": "^5.7.0" + } + }, + "@ethersproject/abstract-provider": { + "version": "5.7.0", + "requires": { + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/networks": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/transactions": "^5.7.0", + "@ethersproject/web": "^5.7.0" + } + }, + "@ethersproject/abstract-signer": { + "version": "5.7.0", + "requires": { + "@ethersproject/abstract-provider": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0" + } + }, + "@ethersproject/address": { + "version": "5.7.0", + "requires": { + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/keccak256": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/rlp": "^5.7.0" + } + }, + "@ethersproject/base64": { + "version": "5.7.0", + "requires": { + "@ethersproject/bytes": "^5.7.0" + } + }, + "@ethersproject/basex": { + "version": "5.7.0", + "requires": { + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/properties": "^5.7.0" + } + }, + "@ethersproject/bignumber": { + "version": "5.7.0", + "requires": { + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "bn.js": "^5.2.1" + } + }, + "@ethersproject/bytes": { + "version": "5.7.0", + "requires": { + "@ethersproject/logger": "^5.7.0" + } + }, + "@ethersproject/constants": { + "version": "5.7.0", + "requires": { + "@ethersproject/bignumber": "^5.7.0" + } + }, + "@ethersproject/contracts": { + "version": "5.7.0", + "requires": { + "@ethersproject/abi": "^5.7.0", + "@ethersproject/abstract-provider": "^5.7.0", + "@ethersproject/abstract-signer": "^5.7.0", + "@ethersproject/address": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/constants": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/transactions": "^5.7.0" + } + }, + "@ethersproject/hash": { + "version": "5.7.0", + "requires": { + "@ethersproject/abstract-signer": "^5.7.0", + "@ethersproject/address": "^5.7.0", + "@ethersproject/base64": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/keccak256": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/strings": "^5.7.0" + } + }, + "@ethersproject/hdnode": { + "version": "5.7.0", + "requires": { + "@ethersproject/abstract-signer": "^5.7.0", + "@ethersproject/basex": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/pbkdf2": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/sha2": "^5.7.0", + "@ethersproject/signing-key": "^5.7.0", + "@ethersproject/strings": "^5.7.0", + "@ethersproject/transactions": "^5.7.0", + "@ethersproject/wordlists": "^5.7.0" + } + }, + "@ethersproject/json-wallets": { + "version": "5.7.0", + "requires": { + "@ethersproject/abstract-signer": "^5.7.0", + "@ethersproject/address": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/hdnode": "^5.7.0", + "@ethersproject/keccak256": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/pbkdf2": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/random": "^5.7.0", + "@ethersproject/strings": "^5.7.0", + "@ethersproject/transactions": "^5.7.0", + "aes-js": "3.0.0", + "scrypt-js": "3.0.1" + } + }, + "@ethersproject/keccak256": { + "version": "5.7.0", + "requires": { + "@ethersproject/bytes": "^5.7.0", + "js-sha3": "0.8.0" + } + }, + "@ethersproject/logger": { + "version": "5.7.0" + }, + "@ethersproject/networks": { + "version": "5.7.1", + "requires": { + "@ethersproject/logger": "^5.7.0" + } + }, + "@ethersproject/pbkdf2": { + "version": "5.7.0", + "requires": { + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/sha2": "^5.7.0" + } + }, + "@ethersproject/properties": { + "version": "5.7.0", + "requires": { + "@ethersproject/logger": "^5.7.0" + } + }, + "@ethersproject/providers": { + "version": "5.7.2", + "requires": { + "@ethersproject/abstract-provider": "^5.7.0", + "@ethersproject/abstract-signer": "^5.7.0", + "@ethersproject/address": "^5.7.0", + "@ethersproject/base64": "^5.7.0", + "@ethersproject/basex": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/constants": "^5.7.0", + "@ethersproject/hash": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/networks": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/random": "^5.7.0", + "@ethersproject/rlp": "^5.7.0", + "@ethersproject/sha2": "^5.7.0", + "@ethersproject/strings": "^5.7.0", + "@ethersproject/transactions": "^5.7.0", + "@ethersproject/web": "^5.7.0", + "bech32": "1.1.4", + "ws": "7.4.6" + }, + "dependencies": { + "ws": { + "version": "7.4.6", + "requires": {} + } + } + }, + "@ethersproject/random": { + "version": "5.7.0", + "requires": { + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0" + } + }, + "@ethersproject/rlp": { + "version": "5.7.0", + "requires": { + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0" + } + }, + "@ethersproject/sha2": { + "version": "5.7.0", + "requires": { + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "hash.js": "1.1.7" + } + }, + "@ethersproject/signing-key": { + "version": "5.7.0", + "requires": { + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "bn.js": "^5.2.1", + "elliptic": "6.5.4", + "hash.js": "1.1.7" + } + }, + "@ethersproject/solidity": { + "version": "5.7.0", + "requires": { + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/keccak256": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/sha2": "^5.7.0", + "@ethersproject/strings": "^5.7.0" + } + }, + "@ethersproject/strings": { + "version": "5.7.0", + "requires": { + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/constants": "^5.7.0", + "@ethersproject/logger": "^5.7.0" + } + }, + "@ethersproject/transactions": { + "version": "5.7.0", + "requires": { + "@ethersproject/address": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/constants": "^5.7.0", + "@ethersproject/keccak256": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/rlp": "^5.7.0", + "@ethersproject/signing-key": "^5.7.0" + } + }, + "@ethersproject/units": { + "version": "5.7.0", + "requires": { + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/constants": "^5.7.0", + "@ethersproject/logger": "^5.7.0" + } + }, + "@ethersproject/wallet": { + "version": "5.7.0", + "requires": { + "@ethersproject/abstract-provider": "^5.7.0", + "@ethersproject/abstract-signer": "^5.7.0", + "@ethersproject/address": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/hash": "^5.7.0", + "@ethersproject/hdnode": "^5.7.0", + "@ethersproject/json-wallets": "^5.7.0", + "@ethersproject/keccak256": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/random": "^5.7.0", + "@ethersproject/signing-key": "^5.7.0", + "@ethersproject/transactions": "^5.7.0", + "@ethersproject/wordlists": "^5.7.0" + } + }, + "@ethersproject/web": { + "version": "5.7.1", + "requires": { + "@ethersproject/base64": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/strings": "^5.7.0" + } + }, + "@ethersproject/wordlists": { + "version": "5.7.0", + "requires": { + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/hash": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/strings": "^5.7.0" + } + }, + "@humanwhocodes/config-array": { + "version": "0.10.7", + "dev": true, + "requires": { + "@humanwhocodes/object-schema": "^1.2.1", + "debug": "^4.1.1", + "minimatch": "^3.0.4" + } + }, + "@humanwhocodes/gitignore-to-minimatch": { + "version": "1.0.2", + "dev": true + }, + "@humanwhocodes/object-schema": { + "version": "1.2.1", + "dev": true + }, + "@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "dev": true, + "requires": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "dependencies": { + "argparse": { + "version": "1.0.10", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "find-up": { + "version": "4.1.0", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "js-yaml": { + "version": "3.14.1", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-limit": { + "version": "2.3.0", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "resolve-from": { + "version": "5.0.0", + "dev": true + }, + "sprintf-js": { + "version": "1.0.3", + "dev": true + } + } + }, + "@istanbuljs/schema": { + "version": "0.1.3", + "dev": true + }, + "@jridgewell/gen-mapping": { + "version": "0.1.1", + "dev": true, + "requires": { + "@jridgewell/set-array": "^1.0.0", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "@jridgewell/resolve-uri": { + "version": "3.1.0", + "dev": true + }, + "@jridgewell/set-array": { + "version": "1.1.2", + "dev": true + }, + "@jridgewell/source-map": { + "version": "0.3.2", + "dev": true, + "requires": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "dependencies": { + "@jridgewell/gen-mapping": { + "version": "0.3.2", + "dev": true, + "requires": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + } + } + } + }, + "@jridgewell/sourcemap-codec": { + "version": "1.4.14", + "dev": true + }, + "@jridgewell/trace-mapping": { + "version": "0.3.17", + "dev": true, + "requires": { + "@jridgewell/resolve-uri": "3.1.0", + "@jridgewell/sourcemap-codec": "1.4.14" + } + }, + "@motrix/nat-api": { + "version": "0.3.2", + "requires": { + "async": "^3.2.0", + "debug": "^4.3.1", + "default-gateway": "^6.0.3", + "request": "^2.88.2", + "unordered-array-remove": "^1.0.2", + "xml2js": "^0.4.23" + } + }, + "@multiformats/base-x": { + "version": "4.0.1" + }, + "@noble/curves": { + "version": "1.0.0", + "requires": { + "@noble/hashes": "1.3.0" + } + }, + "@noble/ed25519": { + "version": "1.7.1" + }, + "@noble/hashes": { + "version": "1.3.0" + }, + "@noble/secp256k1": { + "version": "1.6.3" + }, + "@nodelib/fs.scandir": { + "version": "2.1.5", + "dev": true, + "requires": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + } + }, + "@nodelib/fs.stat": { + "version": "2.0.5", + "dev": true + }, + "@nodelib/fs.walk": { + "version": "1.2.8", + "dev": true, + "requires": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + } + }, + "@protobufjs/aspromise": { + "version": "1.1.2" + }, + "@protobufjs/base64": { + "version": "1.1.2" + }, + "@protobufjs/codegen": { + "version": "2.0.4" + }, + "@protobufjs/eventemitter": { + "version": "1.1.0" + }, + "@protobufjs/fetch": { + "version": "1.1.0", + "requires": { + "@protobufjs/aspromise": "^1.1.1", + "@protobufjs/inquire": "^1.1.0" + } + }, + "@protobufjs/float": { + "version": "1.0.2" + }, + "@protobufjs/inquire": { + "version": "1.1.0" + }, + "@protobufjs/path": { + "version": "1.1.2" + }, + "@protobufjs/pool": { + "version": "1.1.0" + }, + "@protobufjs/utf8": { + "version": "1.1.0" + }, + "@scure/base": { + "version": "1.1.1" + }, + "@scure/bip32": { + "version": "1.3.0", + "requires": { + "@noble/curves": "~1.0.0", + "@noble/hashes": "~1.3.0", + "@scure/base": "~1.1.0" + } + }, + "@scure/bip39": { + "version": "1.2.0", + "requires": { + "@noble/hashes": "~1.3.0", + "@scure/base": "~1.1.0" + } + }, + "@sinonjs/commons": { + "version": "1.8.3", + "requires": { + "type-detect": "4.0.8" + } + }, + "@sinonjs/fake-timers": { + "version": "6.0.1", + "requires": { + "@sinonjs/commons": "^1.7.0" + } + }, + "@sinonjs/samsam": { + "version": "5.3.1", + "requires": { + "@sinonjs/commons": "^1.6.0", + "lodash.get": "^4.4.2", + "type-detect": "^4.0.8" + } + }, + "@sinonjs/text-encoding": { + "version": "0.7.2" + }, + "@socket.io/component-emitter": { + "version": "3.1.0", + "dev": true + }, + "@stablelib/aead": { + "version": "1.0.1" + }, + "@stablelib/binary": { + "version": "1.0.1", + "requires": { + "@stablelib/int": "^1.0.1" + } + }, + "@stablelib/bytes": { + "version": "1.0.1" + }, + "@stablelib/chacha": { + "version": "1.0.1", + "requires": { + "@stablelib/binary": "^1.0.1", + "@stablelib/wipe": "^1.0.1" + } + }, + "@stablelib/chacha20poly1305": { + "version": "1.0.1", + "requires": { + "@stablelib/aead": "^1.0.1", + "@stablelib/binary": "^1.0.1", + "@stablelib/chacha": "^1.0.1", + "@stablelib/constant-time": "^1.0.1", + "@stablelib/poly1305": "^1.0.1", + "@stablelib/wipe": "^1.0.1" + } + }, + "@stablelib/constant-time": { + "version": "1.0.1" + }, + "@stablelib/hash": { + "version": "1.0.1" + }, + "@stablelib/hkdf": { + "version": "1.0.1", + "requires": { + "@stablelib/hash": "^1.0.1", + "@stablelib/hmac": "^1.0.1", + "@stablelib/wipe": "^1.0.1" + } + }, + "@stablelib/hmac": { + "version": "1.0.1", + "requires": { + "@stablelib/constant-time": "^1.0.1", + "@stablelib/hash": "^1.0.1", + "@stablelib/wipe": "^1.0.1" + } + }, + "@stablelib/int": { + "version": "1.0.1" + }, + "@stablelib/keyagreement": { + "version": "1.0.1", + "requires": { + "@stablelib/bytes": "^1.0.1" + } + }, + "@stablelib/poly1305": { + "version": "1.0.1", + "requires": { + "@stablelib/constant-time": "^1.0.1", + "@stablelib/wipe": "^1.0.1" + } + }, + "@stablelib/random": { + "version": "1.0.2", + "requires": { + "@stablelib/binary": "^1.0.1", + "@stablelib/wipe": "^1.0.1" + } + }, + "@stablelib/sha256": { + "version": "1.0.1", + "requires": { + "@stablelib/binary": "^1.0.1", + "@stablelib/hash": "^1.0.1", + "@stablelib/wipe": "^1.0.1" + } + }, + "@stablelib/wipe": { + "version": "1.0.1" + }, + "@stablelib/x25519": { + "version": "1.0.3", + "requires": { + "@stablelib/keyagreement": "^1.0.1", + "@stablelib/random": "^1.0.2", + "@stablelib/wipe": "^1.0.1" + } + }, + "@tsconfig/node10": { + "version": "1.0.9", + "dev": true + }, + "@tsconfig/node12": { + "version": "1.0.11", + "dev": true + }, + "@tsconfig/node14": { + "version": "1.0.3", + "dev": true + }, + "@tsconfig/node16": { + "version": "1.0.3", + "dev": true + }, + "@types/async": { + "version": "2.4.2", + "dev": true + }, + "@types/benchmark": { + "version": "1.0.33", + "dev": true + }, + "@types/bl": { + "version": "2.1.0", + "requires": { + "@types/node": "*" + } + }, + "@types/bn.js": { + "version": "5.1.1", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/body-parser": { + "version": "1.19.2", + "dev": true, + "requires": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "@types/chalk": { + "version": "2.2.0", + "dev": true, + "requires": { + "chalk": "*" + } + }, + "@types/connect": { + "version": "3.4.35", + "requires": { + "@types/node": "*" + } + }, + "@types/cookie": { + "version": "0.4.1", + "dev": true + }, + "@types/cookiejar": { + "version": "2.1.2", + "dev": true + }, + "@types/core-js": { + "version": "2.5.5", + "dev": true + }, + "@types/cors": { + "version": "2.8.12", + "dev": true + }, + "@types/debug": { + "version": "4.1.7", + "dev": true, + "requires": { + "@types/ms": "*" + } + }, + "@types/eslint": { + "version": "8.4.7", + "dev": true, + "requires": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "@types/eslint-scope": { + "version": "3.7.4", + "dev": true, + "requires": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, + "@types/estree": { + "version": "0.0.51", + "dev": true + }, + "@types/fs-extra": { + "version": "9.0.13", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/glob": { + "version": "7.2.0", + "dev": true, + "requires": { + "@types/minimatch": "*", + "@types/node": "*" + } + }, + "@types/ip": { + "version": "1.1.0", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/istanbul-lib-coverage": { + "version": "2.0.4", + "dev": true + }, + "@types/json-schema": { + "version": "7.0.11", + "dev": true + }, + "@types/json5": { + "version": "0.0.29", + "dev": true + }, + "@types/jwt-simple": { + "version": "0.5.33", + "dev": true + }, + "@types/k-bucket": { + "version": "5.0.1", + "requires": { + "@types/node": "*" + } + }, + "@types/level-errors": { + "version": "3.0.0", + "dev": true + }, + "@types/long": { + "version": "4.0.2" + }, + "@types/minimatch": { + "version": "3.0.5" + }, + "@types/minimist": { + "version": "1.2.2", + "dev": true + }, + "@types/ms": { + "version": "0.7.31", + "dev": true + }, + "@types/node": { + "version": "16.11.49" + }, + "@types/node-dir": { + "version": "0.0.34", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/readable-stream": { + "version": "2.3.14", + "requires": { + "@types/node": "*", + "safe-buffer": "*" + } + }, + "@types/retry": { + "version": "0.12.0" + }, + "@types/secp256k1": { + "version": "4.0.3", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/superagent": { + "version": "4.1.15", + "dev": true, + "requires": { + "@types/cookiejar": "*", + "@types/node": "*" + } + }, + "@types/supertest": { + "version": "2.0.12", + "dev": true, + "requires": { + "@types/superagent": "*" + } + }, + "@types/tape": { + "version": "4.13.2", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/ws": { + "version": "7.4.7", + "requires": { + "@types/node": "*" + } + }, + "@types/yargs": { + "version": "17.0.24", + "dev": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "@types/yargs-parser": { + "version": "21.0.0", + "dev": true + }, + "@typescript-eslint/eslint-plugin": { + "version": "5.33.1", + "dev": true, + "requires": { + "@typescript-eslint/scope-manager": "5.33.1", + "@typescript-eslint/type-utils": "5.33.1", + "@typescript-eslint/utils": "5.33.1", + "debug": "^4.3.4", + "functional-red-black-tree": "^1.0.1", + "ignore": "^5.2.0", + "regexpp": "^3.2.0", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + } + }, + "@typescript-eslint/parser": { + "version": "5.33.1", + "dev": true, + "requires": { + "@typescript-eslint/scope-manager": "5.33.1", + "@typescript-eslint/types": "5.33.1", + "@typescript-eslint/typescript-estree": "5.33.1", + "debug": "^4.3.4" + } + }, + "@typescript-eslint/scope-manager": { + "version": "5.33.1", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.33.1", + "@typescript-eslint/visitor-keys": "5.33.1" + } + }, + "@typescript-eslint/type-utils": { + "version": "5.33.1", + "dev": true, + "requires": { + "@typescript-eslint/utils": "5.33.1", + "debug": "^4.3.4", + "tsutils": "^3.21.0" + } + }, + "@typescript-eslint/types": { + "version": "5.33.1", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "5.33.1", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.33.1", + "@typescript-eslint/visitor-keys": "5.33.1", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + } + }, + "@typescript-eslint/utils": { + "version": "5.33.1", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.9", + "@typescript-eslint/scope-manager": "5.33.1", + "@typescript-eslint/types": "5.33.1", + "@typescript-eslint/typescript-estree": "5.33.1", + "eslint-scope": "^5.1.1", + "eslint-utils": "^3.0.0" + } + }, + "@typescript-eslint/visitor-keys": { + "version": "5.33.1", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.33.1", + "eslint-visitor-keys": "^3.3.0" + } + }, + "@webassemblyjs/ast": { + "version": "1.11.1", + "dev": true, + "requires": { + "@webassemblyjs/helper-numbers": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1" + } + }, + "@webassemblyjs/floating-point-hex-parser": { + "version": "1.11.1", + "dev": true + }, + "@webassemblyjs/helper-api-error": { + "version": "1.11.1", + "dev": true + }, + "@webassemblyjs/helper-buffer": { + "version": "1.11.1", + "dev": true + }, + "@webassemblyjs/helper-numbers": { + "version": "1.11.1", + "dev": true, + "requires": { + "@webassemblyjs/floating-point-hex-parser": "1.11.1", + "@webassemblyjs/helper-api-error": "1.11.1", + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/helper-wasm-bytecode": { + "version": "1.11.1", + "dev": true + }, + "@webassemblyjs/helper-wasm-section": { + "version": "1.11.1", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1" + } + }, + "@webassemblyjs/ieee754": { + "version": "1.11.1", + "dev": true, + "requires": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "@webassemblyjs/leb128": { + "version": "1.11.1", + "dev": true, + "requires": { + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/utf8": { + "version": "1.11.1", + "dev": true + }, + "@webassemblyjs/wasm-edit": { + "version": "1.11.1", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/helper-wasm-section": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1", + "@webassemblyjs/wasm-opt": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1", + "@webassemblyjs/wast-printer": "1.11.1" + } + }, + "@webassemblyjs/wasm-gen": { + "version": "1.11.1", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/ieee754": "1.11.1", + "@webassemblyjs/leb128": "1.11.1", + "@webassemblyjs/utf8": "1.11.1" + } + }, + "@webassemblyjs/wasm-opt": { + "version": "1.11.1", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1" + } + }, + "@webassemblyjs/wasm-parser": { + "version": "1.11.1", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-api-error": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/ieee754": "1.11.1", + "@webassemblyjs/leb128": "1.11.1", + "@webassemblyjs/utf8": "1.11.1" + } + }, + "@webassemblyjs/wast-printer": { + "version": "1.11.1", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@xtuc/long": "4.2.2" + } + }, + "@webpack-cli/configtest": { + "version": "1.2.0", + "dev": true, + "requires": {} + }, + "@webpack-cli/info": { + "version": "1.5.0", + "dev": true, + "requires": { + "envinfo": "^7.7.3" + } + }, + "@webpack-cli/serve": { + "version": "1.7.0", + "dev": true, + "requires": {} + }, + "@xtuc/ieee754": { + "version": "1.2.0", + "dev": true + }, + "@xtuc/long": { + "version": "4.2.2", + "dev": true + }, + "@zxing/text-encoding": { + "version": "0.9.0", + "optional": true + }, + "0x": { + "version": "4.11.0", + "dev": true, + "requires": { + "ajv": "^6.9.2", + "browserify": "^16.2.3", + "concat-stream": "^1.5.2", + "d3-fg": "^6.14.0", + "debounce": "^1.2.0", + "debug": "^4.1.1", + "end-of-stream": "^1.1.0", + "env-string": "^1.0.0", + "escape-string-regexp": "^1.0.5", + "execspawn": "^1.0.1", + "has-unicode": "^2.0.1", + "hsl-to-rgb-for-reals": "^1.1.0", + "jsonstream2": "^1.1.2", + "make-dir": "^1.3.0", + "minimist": "^1.2.0", + "morphdom": "^2.3.3", + "nanohtml": "^1.4.0", + "on-net-listen": "^1.1.0", + "opn": "^5.4.0", + "perf-sym": "^2.0.3", + "pump": "^3.0.0", + "pumpify": "^1.4.0", + "semver": "^5.5.1", + "single-line-log": "^1.0.1", + "split2": "^3.1.0", + "tachyons": "^4.9.1", + "through2": "^2.0.5", + "which": "^1.2.4" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "dev": true + } + } + }, + "abort-controller": { + "version": "3.0.0", + "requires": { + "event-target-shim": "^5.0.0" + } + }, + "abortable-iterator": { + "version": "3.0.2", + "requires": { + "get-iterator": "^1.0.2" + } + }, + "abstract-level": { + "version": "1.0.3", + "requires": { + "buffer": "^6.0.3", + "catering": "^2.1.0", + "is-buffer": "^2.0.5", + "level-supports": "^4.0.0", + "level-transcoder": "^1.0.1", + "module-error": "^1.0.1", + "queue-microtask": "^1.2.3" + } + }, + "abstract-leveldown": { + "version": "7.2.0", + "dev": true, + "requires": { + "buffer": "^6.0.3", + "catering": "^2.0.0", + "is-buffer": "^2.0.5", + "level-concat-iterator": "^3.0.0", + "level-supports": "^2.0.1", + "queue-microtask": "^1.2.3" + }, + "dependencies": { + "level-supports": { + "version": "2.1.0", + "dev": true + } + } + }, + "accepts": { + "version": "1.3.8", + "dev": true, + "requires": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + } + }, + "acorn": { + "version": "8.8.0", + "dev": true + }, + "acorn-import-assertions": { + "version": "1.8.0", + "dev": true, + "requires": {} + }, + "acorn-jsx": { + "version": "5.3.2", + "dev": true, + "requires": {} + }, + "acorn-node": { + "version": "1.8.2", + "dev": true, + "requires": { + "acorn": "^7.0.0", + "acorn-walk": "^7.0.0", + "xtend": "^4.0.2" + }, + "dependencies": { + "acorn": { + "version": "7.4.1", + "dev": true + } + } + }, + "acorn-walk": { + "version": "7.2.0", + "dev": true + }, + "aes-js": { + "version": "3.0.0" + }, + "aggregate-error": { + "version": "3.1.0", + "requires": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + } + }, + "ajv": { + "version": "6.12.6", + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ajv-keywords": { + "version": "3.5.2", + "dev": true, + "requires": {} + }, + "ansi-escapes": { + "version": "4.3.2", + "dev": true, + "requires": { + "type-fest": "^0.21.3" + }, + "dependencies": { + "type-fest": { + "version": "0.21.3", + "dev": true + } + } + }, + "ansi-regex": { + "version": "5.0.1" + }, + "ansi-styles": { + "version": "4.3.0", + "requires": { + "color-convert": "^2.0.1" + } + }, + "ansicolors": { + "version": "0.2.1", + "dev": true + }, + "any-signal": { + "version": "2.1.2", + "requires": { + "abort-controller": "^3.0.0", + "native-abort-controller": "^1.0.3" + } + }, + "anymatch": { + "version": "3.1.2", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "append-transform": { + "version": "2.0.0", + "dev": true, + "requires": { + "default-require-extensions": "^3.0.0" + } + }, + "archy": { + "version": "1.0.0", + "dev": true + }, + "arg": { + "version": "4.1.3", + "dev": true + }, + "argparse": { + "version": "2.0.1", + "dev": true + }, + "aria-query": { + "version": "4.2.2", + "dev": true, + "requires": { + "@babel/runtime": "^7.10.2", + "@babel/runtime-corejs3": "^7.10.2" + } + }, + "array-includes": { + "version": "3.1.5", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.19.5", + "get-intrinsic": "^1.1.1", + "is-string": "^1.0.7" + } + }, + "array-union": { + "version": "2.1.0", + "dev": true + }, + "array.prototype.every": { + "version": "1.1.3", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.0", + "is-string": "^1.0.7" + } + }, + "array.prototype.find": { + "version": "2.2.0", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.4", + "es-shim-unscopables": "^1.0.0" + } + }, + "array.prototype.flat": { + "version": "1.3.0", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.2", + "es-shim-unscopables": "^1.0.0" + } + }, + "asap": { + "version": "2.0.6", + "dev": true + }, + "asn1": { + "version": "0.2.6", + "requires": { + "safer-buffer": "~2.1.0" + } + }, + "asn1.js": { + "version": "5.4.1", + "requires": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "safer-buffer": "^2.1.0" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0" + } + } + }, + "assert": { + "version": "1.5.0", + "dev": true, + "requires": { + "object-assign": "^4.1.1", + "util": "0.10.3" + }, + "dependencies": { + "inherits": { + "version": "2.0.1", + "dev": true + }, + "util": { + "version": "0.10.3", + "dev": true, + "requires": { + "inherits": "2.0.1" + } + } + } + }, + "assert-plus": { + "version": "1.0.0" + }, + "assertion-error": { + "version": "1.1.0" + }, + "ast-types-flow": { + "version": "0.0.7", + "dev": true + }, + "astral-regex": { + "version": "2.0.0", + "dev": true + }, + "async": { + "version": "3.2.4" + }, + "asynckit": { + "version": "0.4.0" + }, + "atomic-sleep": { + "version": "1.0.0", + "dev": true + }, + "available-typed-arrays": { + "version": "1.0.5" + }, + "aws-sign2": { + "version": "0.7.0" + }, + "aws4": { + "version": "1.11.0" + }, + "axe-core": { + "version": "4.4.3", + "dev": true + }, + "axobject-query": { + "version": "2.2.0", + "dev": true + }, + "babel-code-frame": { + "version": "6.26.0", + "dev": true, + "requires": { + "chalk": "^1.1.3", + "esutils": "^2.0.2", + "js-tokens": "^3.0.2" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "js-tokens": { + "version": "3.0.2", + "dev": true + }, + "strip-ansi": { + "version": "3.0.1", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "dev": true + } + } + }, + "babel-plugin-polyfill-corejs2": { + "version": "0.3.3", + "dev": true, + "requires": { + "@babel/compat-data": "^7.17.7", + "@babel/helper-define-polyfill-provider": "^0.3.3", + "semver": "^6.1.1" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "dev": true + } + } + }, + "babel-plugin-polyfill-corejs3": { + "version": "0.6.0", + "dev": true, + "requires": { + "@babel/helper-define-polyfill-provider": "^0.3.3", + "core-js-compat": "^3.25.1" + } + }, + "babel-plugin-polyfill-regenerator": { + "version": "0.4.1", + "dev": true, + "requires": { + "@babel/helper-define-polyfill-provider": "^0.3.3" + } + }, + "babel-polyfill": { + "version": "6.26.0", + "dev": true, + "requires": { + "babel-runtime": "^6.26.0", + "core-js": "^2.5.0", + "regenerator-runtime": "^0.10.5" + }, + "dependencies": { + "regenerator-runtime": { + "version": "0.10.5", + "dev": true + } + } + }, + "babel-runtime": { + "version": "6.26.0", + "dev": true, + "requires": { + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" + }, + "dependencies": { + "regenerator-runtime": { + "version": "0.11.1", + "dev": true + } + } + }, + "balanced-match": { + "version": "1.0.2" + }, + "base32.js": { + "version": "0.1.0" + }, + "base64-js": { + "version": "1.5.1" + }, + "base64id": { + "version": "2.0.0", + "dev": true + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "bech32": { + "version": "1.1.4" + }, + "benchmark": { + "version": "2.1.4", + "dev": true, + "requires": { + "lodash": "^4.17.4", + "platform": "^1.3.3" + } + }, + "big.js": { + "version": "5.2.2", + "dev": true + }, + "bigint-crypto-utils": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/bigint-crypto-utils/-/bigint-crypto-utils-3.2.2.tgz", + "integrity": "sha512-U1RbE3aX9ayCUVcIPHuPDPKcK3SFOXf93J1UK/iHlJuQB7bhagPIX06/CLpLEsDThJ7KA4Dhrnzynl+d2weTiw==" + }, + "bignumber.js": { + "version": "9.1.0" + }, + "binary-extensions": { + "version": "2.2.0", + "dev": true + }, + "bindings": { + "version": "1.5.0", + "requires": { + "file-uri-to-path": "1.0.0" + } + }, + "blakejs": { + "version": "1.2.1" + }, + "bn.js": { + "version": "5.2.1" + }, + "body-parser": { + "version": "1.20.1", + "requires": { + "bytes": "3.1.2", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.1", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0" + } + } + }, + "brace-expansion": { + "version": "1.1.11", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "3.0.2", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "brorand": { + "version": "1.1.0" + }, + "browser-level": { + "version": "1.0.1", + "requires": { + "abstract-level": "^1.0.2", + "catering": "^2.1.1", + "module-error": "^1.0.2", + "run-parallel-limit": "^1.1.0" + } + }, + "browser-pack": { + "version": "6.1.0", + "dev": true, + "requires": { + "combine-source-map": "~0.8.0", + "defined": "^1.0.0", + "JSONStream": "^1.0.3", + "safe-buffer": "^5.1.1", + "through2": "^2.0.0", + "umd": "^3.0.0" + } + }, + "browser-process-hrtime": { + "version": "0.1.3", + "dev": true + }, + "browser-resolve": { + "version": "2.0.0", + "dev": true, + "requires": { + "resolve": "^1.17.0" + } + }, + "browserify": { + "version": "16.5.2", + "dev": true, + "requires": { + "assert": "^1.4.0", + "browser-pack": "^6.0.1", + "browser-resolve": "^2.0.0", + "browserify-zlib": "~0.2.0", + "buffer": "~5.2.1", + "cached-path-relative": "^1.0.0", + "concat-stream": "^1.6.0", + "console-browserify": "^1.1.0", + "constants-browserify": "~1.0.0", + "crypto-browserify": "^3.0.0", + "defined": "^1.0.0", + "deps-sort": "^2.0.0", + "domain-browser": "^1.2.0", + "duplexer2": "~0.1.2", + "events": "^2.0.0", + "glob": "^7.1.0", + "has": "^1.0.0", + "htmlescape": "^1.1.0", + "https-browserify": "^1.0.0", + "inherits": "~2.0.1", + "insert-module-globals": "^7.0.0", + "JSONStream": "^1.0.3", + "labeled-stream-splicer": "^2.0.0", + "mkdirp-classic": "^0.5.2", + "module-deps": "^6.2.3", + "os-browserify": "~0.3.0", + "parents": "^1.0.1", + "path-browserify": "~0.0.0", + "process": "~0.11.0", + "punycode": "^1.3.2", + "querystring-es3": "~0.2.0", + "read-only-stream": "^2.0.0", + "readable-stream": "^2.0.2", + "resolve": "^1.1.4", + "shasum": "^1.0.0", + "shell-quote": "^1.6.1", + "stream-browserify": "^2.0.0", + "stream-http": "^3.0.0", + "string_decoder": "^1.1.1", + "subarg": "^1.0.0", + "syntax-error": "^1.1.1", + "through2": "^2.0.0", + "timers-browserify": "^1.0.1", + "tty-browserify": "0.0.1", + "url": "~0.11.0", + "util": "~0.10.1", + "vm-browserify": "^1.0.0", + "xtend": "^4.0.0" + }, + "dependencies": { + "buffer": { + "version": "5.2.1", + "dev": true, + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "inherits": { + "version": "2.0.3", + "dev": true + }, + "stream-browserify": { + "version": "2.0.2", + "dev": true, + "requires": { + "inherits": "~2.0.1", + "readable-stream": "^2.0.2" + } + }, + "util": { + "version": "0.10.4", + "dev": true, + "requires": { + "inherits": "2.0.3" + } + } + } + }, + "browserify-aes": { + "version": "1.2.0", + "dev": true, + "requires": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "browserify-cipher": { + "version": "1.0.1", + "dev": true, + "requires": { + "browserify-aes": "^1.0.4", + "browserify-des": "^1.0.0", + "evp_bytestokey": "^1.0.0" + } + }, + "browserify-des": { + "version": "1.0.2", + "dev": true, + "requires": { + "cipher-base": "^1.0.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "browserify-rsa": { + "version": "4.1.0", + "dev": true, + "requires": { + "bn.js": "^5.0.0", + "randombytes": "^2.0.1" + } + }, + "browserify-sign": { + "version": "4.2.1", + "dev": true, + "requires": { + "bn.js": "^5.1.1", + "browserify-rsa": "^4.0.1", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "elliptic": "^6.5.3", + "inherits": "^2.0.4", + "parse-asn1": "^5.1.5", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "browserify-zlib": { + "version": "0.2.0", + "dev": true, + "requires": { + "pako": "~1.0.5" + } + }, + "browserslist": { + "version": "4.21.4", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30001400", + "electron-to-chromium": "^1.4.251", + "node-releases": "^2.0.6", + "update-browserslist-db": "^1.0.9" + } + }, + "buffer": { + "version": "6.0.3", + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "buffer-from": { + "version": "1.1.2", + "dev": true + }, + "buffer-xor": { + "version": "1.0.3", + "dev": true + }, + "builtin-modules": { + "version": "1.1.1", + "dev": true + }, + "builtin-status-codes": { + "version": "3.0.0", + "dev": true + }, + "bytes": { + "version": "3.1.2" + }, + "c-kzg": { + "version": "2.0.4", + "requires": { + "bindings": "^1.5.0", + "node-addon-api": "^5.0.0" + }, + "dependencies": { + "node-addon-api": { + "version": "5.1.0" + } + } + }, + "c8": { + "version": "7.12.0", + "dev": true, + "requires": { + "@bcoe/v8-coverage": "^0.2.3", + "@istanbuljs/schema": "^0.1.3", + "find-up": "^5.0.0", + "foreground-child": "^2.0.0", + "istanbul-lib-coverage": "^3.2.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-reports": "^3.1.4", + "rimraf": "^3.0.2", + "test-exclude": "^6.0.0", + "v8-to-istanbul": "^9.0.0", + "yargs": "^16.2.0", + "yargs-parser": "^20.2.9" + } + }, + "cached-path-relative": { + "version": "1.1.0", + "dev": true + }, + "caching-transform": { + "version": "4.0.0", + "dev": true, + "requires": { + "hasha": "^5.0.0", + "make-dir": "^3.0.0", + "package-hash": "^4.0.0", + "write-file-atomic": "^3.0.0" + }, + "dependencies": { + "make-dir": { + "version": "3.1.0", + "dev": true, + "requires": { + "semver": "^6.0.0" + } + }, + "semver": { + "version": "6.3.0", + "dev": true + } + } + }, + "call-bind": { + "version": "1.0.2", + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + } + }, + "caller-path": { + "version": "0.1.0", + "dev": true, + "requires": { + "callsites": "^0.2.0" + }, + "dependencies": { + "callsites": { + "version": "0.2.0", + "dev": true + } + } + }, + "callsites": { + "version": "3.1.0", + "dev": true + }, + "camel-case": { + "version": "3.0.0", + "dev": true, + "requires": { + "no-case": "^2.2.0", + "upper-case": "^1.1.1" + } + }, + "camelcase": { + "version": "5.3.1", + "dev": true + }, + "caniuse-lite": { + "version": "1.0.30001423", + "dev": true + }, + "caseless": { + "version": "0.12.0" + }, + "catering": { + "version": "2.1.1" + }, + "chai": { + "version": "4.3.6", + "requires": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.2", + "deep-eql": "^3.0.1", + "get-func-name": "^2.0.0", + "loupe": "^2.3.1", + "pathval": "^1.1.1", + "type-detect": "^4.0.5" + } + }, + "chai-checkmark": { + "version": "1.0.1" + }, + "chalk": { + "version": "4.1.2", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "check-error": { + "version": "1.0.2" + }, + "chokidar": { + "version": "3.5.3", + "dev": true, + "requires": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "fsevents": "~2.3.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "dependencies": { + "glob-parent": { + "version": "5.1.2", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + } + } + }, + "chrome-trace-event": { + "version": "1.0.3", + "dev": true + }, + "cids": { + "version": "1.1.9", + "requires": { + "multibase": "^4.0.1", + "multicodec": "^3.0.1", + "multihashes": "^4.0.1", + "uint8arrays": "^3.0.0" + }, + "dependencies": { + "multicodec": { + "version": "3.2.1", + "requires": { + "uint8arrays": "^3.0.0", + "varint": "^6.0.0" + } + } + } + }, + "cipher-base": { + "version": "1.0.4", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "circular-json": { + "version": "0.3.3", + "dev": true + }, + "class-is": { + "version": "1.1.0" + }, + "classic-level": { + "version": "1.2.0", + "requires": { + "abstract-level": "^1.0.2", + "catering": "^2.1.0", + "module-error": "^1.0.1", + "napi-macros": "~2.0.0", + "node-gyp-build": "^4.3.0" + } + }, + "clean-stack": { + "version": "2.2.0" + }, + "cli-cursor": { + "version": "3.1.0", + "dev": true, + "requires": { + "restore-cursor": "^3.1.0" + } + }, + "cli-truncate": { + "version": "3.1.0", + "dev": true, + "requires": { + "slice-ansi": "^5.0.0", + "string-width": "^5.0.0" + } + }, + "cli-width": { + "version": "2.2.1", + "dev": true + }, + "cliui": { + "version": "7.0.4", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + }, + "dependencies": { + "emoji-regex": { + "version": "8.0.0", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "dev": true + }, + "string-width": { + "version": "4.2.3", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + } + } + }, + "clone": { + "version": "1.0.4", + "dev": true + }, + "clone-deep": { + "version": "4.0.1", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + } + }, + "co": { + "version": "4.6.0", + "dev": true + }, + "code-point-at": { + "version": "1.1.0", + "dev": true + }, + "color": { + "version": "3.2.1", + "requires": { + "color-convert": "^1.9.3", + "color-string": "^1.6.0" + }, + "dependencies": { + "color-convert": { + "version": "1.9.3", + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3" + } + } + }, + "color-convert": { + "version": "2.0.1", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4" + }, + "color-string": { + "version": "1.9.1", + "requires": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, + "colorette": { + "version": "2.0.19", + "dev": true + }, + "colors": { + "version": "0.6.2", + "dev": true + }, + "colorspace": { + "version": "1.1.4", + "requires": { + "color": "^3.1.3", + "text-hex": "1.0.x" + } + }, + "combine-source-map": { + "version": "0.8.0", + "dev": true, + "requires": { + "convert-source-map": "~1.1.0", + "inline-source-map": "~0.6.0", + "lodash.memoize": "~3.0.3", + "source-map": "~0.5.3" + } + }, + "combined-stream": { + "version": "1.0.8", + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "command-exists": { + "version": "1.2.9", + "dev": true + }, + "commander": { + "version": "2.1.0", + "dev": true + }, + "commondir": { + "version": "1.0.1", + "dev": true + }, + "component-emitter": { + "version": "1.3.0", + "dev": true + }, + "concat-map": { + "version": "0.0.1" + }, + "concat-stream": { + "version": "1.6.2", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "connect": { + "version": "3.7.0", + "requires": { + "debug": "2.6.9", + "finalhandler": "1.1.2", + "parseurl": "~1.3.3", + "utils-merge": "1.0.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0" + } + } + }, + "console-browserify": { + "version": "1.2.0", + "dev": true + }, + "constants-browserify": { + "version": "1.0.0", + "dev": true + }, + "contains-path": { + "version": "0.1.0", + "dev": true + }, + "content-type": { + "version": "1.0.4" + }, + "convert-source-map": { + "version": "1.1.3", + "dev": true + }, + "cookie": { + "version": "0.4.2", + "dev": true + }, + "cookiejar": { + "version": "2.1.3", + "dev": true + }, + "core-js": { + "version": "2.6.12", + "dev": true + }, + "core-js-compat": { + "version": "3.25.5", + "dev": true, + "requires": { + "browserslist": "^4.21.4" + } + }, + "core-js-pure": { + "version": "3.25.5", + "dev": true + }, + "core-util-is": { + "version": "1.0.3", + "dev": true + }, + "cors": { + "version": "2.8.5", + "requires": { + "object-assign": "^4", + "vary": "^1" + } + }, + "crc-32": { + "version": "1.2.2" + }, + "create-ecdh": { + "version": "4.0.4", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "elliptic": "^6.5.3" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "dev": true + } + } + }, + "create-hash": { + "version": "1.2.0", + "dev": true, + "requires": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "create-hmac": { + "version": "1.1.7", + "dev": true, + "requires": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "create-require": { + "version": "1.1.1", + "dev": true + }, + "cross-spawn": { + "version": "7.0.3", + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "dependencies": { + "which": { + "version": "2.0.2", + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "crypto-browserify": { + "version": "3.12.0", + "dev": true, + "requires": { + "browserify-cipher": "^1.0.0", + "browserify-sign": "^4.0.0", + "create-ecdh": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.0", + "diffie-hellman": "^5.0.0", + "inherits": "^2.0.1", + "pbkdf2": "^3.0.3", + "public-encrypt": "^4.0.0", + "randombytes": "^2.0.0", + "randomfill": "^1.0.3" + } + }, + "custom-event": { + "version": "1.0.1", + "dev": true + }, + "d": { + "version": "1.0.1", + "dev": true, + "requires": { + "es5-ext": "^0.10.50", + "type": "^1.0.1" + } + }, + "d3-array": { + "version": "2.12.1", + "dev": true, + "requires": { + "internmap": "^1.0.0" + } + }, + "d3-color": { + "version": "2.0.0", + "dev": true + }, + "d3-dispatch": { + "version": "1.0.6", + "dev": true + }, + "d3-drag": { + "version": "1.2.5", + "dev": true, + "requires": { + "d3-dispatch": "1", + "d3-selection": "1" + } + }, + "d3-ease": { + "version": "1.0.7", + "dev": true + }, + "d3-fg": { + "version": "6.14.0", + "dev": true, + "requires": { + "d3-array": "^2.2.0", + "d3-dispatch": "^1.0.5", + "d3-ease": "^1.0.5", + "d3-hierarchy": "^1.1.8", + "d3-scale": "^3.0.0", + "d3-selection": "^1.4.0", + "d3-zoom": "^1.7.3", + "escape-string-regexp": "^1.0.5", + "hsl-to-rgb-for-reals": "^1.1.0" + } + }, + "d3-format": { + "version": "2.0.0", + "dev": true + }, + "d3-hierarchy": { + "version": "1.1.9", + "dev": true + }, + "d3-interpolate": { + "version": "2.0.1", + "dev": true, + "requires": { + "d3-color": "1 - 2" + } + }, + "d3-scale": { + "version": "3.3.0", + "dev": true, + "requires": { + "d3-array": "^2.3.0", + "d3-format": "1 - 2", + "d3-interpolate": "1.2.0 - 2", + "d3-time": "^2.1.1", + "d3-time-format": "2 - 3" + } + }, + "d3-selection": { + "version": "1.4.2", + "dev": true + }, + "d3-time": { + "version": "2.1.1", + "dev": true, + "requires": { + "d3-array": "2" + } + }, + "d3-time-format": { + "version": "3.0.0", + "dev": true, + "requires": { + "d3-time": "1 - 2" + } + }, + "d3-timer": { + "version": "1.0.10", + "dev": true + }, + "d3-transition": { + "version": "1.3.2", + "dev": true, + "requires": { + "d3-color": "1", + "d3-dispatch": "1", + "d3-ease": "1", + "d3-interpolate": "1", + "d3-selection": "^1.1.0", + "d3-timer": "1" + }, + "dependencies": { + "d3-color": { + "version": "1.4.1", + "dev": true + }, + "d3-interpolate": { + "version": "1.4.0", + "dev": true, + "requires": { + "d3-color": "1" + } + } + } + }, + "d3-zoom": { + "version": "1.8.3", + "dev": true, + "requires": { + "d3-dispatch": "1", + "d3-drag": "1", + "d3-interpolate": "1", + "d3-selection": "1", + "d3-transition": "1" + }, + "dependencies": { + "d3-color": { + "version": "1.4.1", + "dev": true + }, + "d3-interpolate": { + "version": "1.4.0", + "dev": true, + "requires": { + "d3-color": "1" + } + } + } + }, + "damerau-levenshtein": { + "version": "1.0.8", + "dev": true + }, + "dash-ast": { + "version": "1.0.0", + "dev": true + }, + "dashdash": { + "version": "1.14.1", + "requires": { + "assert-plus": "^1.0.0" + } + }, + "date-format": { + "version": "4.0.14", + "dev": true + }, + "debounce": { + "version": "1.2.1", + "dev": true + }, + "debug": { + "version": "4.3.4", + "requires": { + "ms": "2.1.2" + }, + "dependencies": { + "ms": { + "version": "2.1.2" + } + } + }, + "debug-log": { + "version": "1.0.1", + "dev": true + }, + "decamelize": { + "version": "1.2.0", + "dev": true + }, + "deep-eql": { + "version": "3.0.1", + "requires": { + "type-detect": "^4.0.0" + } + }, + "deep-equal": { + "version": "2.0.5", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "es-get-iterator": "^1.1.1", + "get-intrinsic": "^1.0.1", + "is-arguments": "^1.0.4", + "is-date-object": "^1.0.2", + "is-regex": "^1.1.1", + "isarray": "^2.0.5", + "object-is": "^1.1.4", + "object-keys": "^1.1.1", + "object.assign": "^4.1.2", + "regexp.prototype.flags": "^1.3.0", + "side-channel": "^1.0.3", + "which-boxed-primitive": "^1.0.1", + "which-collection": "^1.0.1", + "which-typed-array": "^1.1.2" + }, + "dependencies": { + "isarray": { + "version": "2.0.5", + "dev": true + } + } + }, + "deep-is": { + "version": "0.1.4", + "dev": true + }, + "default-gateway": { + "version": "6.0.3", + "requires": { + "execa": "^5.0.0" + } + }, + "default-require-extensions": { + "version": "3.0.1", + "dev": true, + "requires": { + "strip-bom": "^4.0.0" + } + }, + "defaults": { + "version": "1.0.4", + "dev": true, + "requires": { + "clone": "^1.0.2" + } + }, + "deferred-leveldown": { + "version": "7.0.0", + "dev": true, + "requires": { + "abstract-leveldown": "^7.2.0", + "inherits": "^2.0.3" + } + }, + "define-properties": { + "version": "1.1.4", + "requires": { + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + } + }, + "defined": { + "version": "1.0.1", + "dev": true + }, + "deglob": { + "version": "2.1.1", + "dev": true, + "requires": { + "find-root": "^1.0.0", + "glob": "^7.0.5", + "ignore": "^3.0.9", + "pkg-config": "^1.1.0", + "run-parallel": "^1.1.2", + "uniq": "^1.0.1" + }, + "dependencies": { + "ignore": { + "version": "3.3.10", + "dev": true + } + } + }, + "delay": { + "version": "5.0.0" + }, + "delayed-stream": { + "version": "1.0.0" + }, + "depd": { + "version": "2.0.0" + }, + "deps-sort": { + "version": "2.0.1", + "dev": true, + "requires": { + "JSONStream": "^1.0.3", + "shasum-object": "^1.0.0", + "subarg": "^1.0.0", + "through2": "^2.0.0" + } + }, + "des.js": { + "version": "1.0.1", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "destroy": { + "version": "1.2.0" + }, + "detect-indent": { + "version": "6.1.0", + "dev": true + }, + "detect-newline": { + "version": "3.1.0", + "dev": true + }, + "detect-node": { + "version": "2.1.0" + }, + "detective": { + "version": "5.2.1", + "dev": true, + "requires": { + "acorn-node": "^1.8.2", + "defined": "^1.0.0", + "minimist": "^1.2.6" + } + }, + "dezalgo": { + "version": "1.0.3", + "dev": true, + "requires": { + "asap": "^2.0.0", + "wrappy": "1" + } + }, + "di": { + "version": "0.0.1", + "dev": true + }, + "diff": { + "version": "4.0.2" + }, + "diffie-hellman": { + "version": "5.0.3", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "dev": true + } + } + }, + "dir-glob": { + "version": "3.0.1", + "dev": true, + "requires": { + "path-type": "^4.0.0" + } + }, + "dirty-chai": { + "version": "2.0.1", + "requires": {} + }, + "dns-over-http-resolver": { + "version": "1.2.3", + "requires": { + "debug": "^4.3.1", + "native-fetch": "^3.0.0", + "receptacle": "^1.3.2" + } + }, + "doctrine": { + "version": "3.0.0", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "dom-serialize": { + "version": "2.2.1", + "dev": true, + "requires": { + "custom-event": "~1.0.0", + "ent": "~2.2.0", + "extend": "^3.0.0", + "void-elements": "^2.0.0" + } + }, + "domain-browser": { + "version": "1.2.0", + "dev": true + }, + "dotignore": { + "version": "0.1.2", + "dev": true, + "requires": { + "minimatch": "^3.0.4" + } + }, + "duplexer2": { + "version": "0.1.4", + "dev": true, + "requires": { + "readable-stream": "^2.0.2" + } + }, + "duplexify": { + "version": "3.7.1", + "dev": true, + "requires": { + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" + } + }, + "eastasianwidth": { + "version": "0.2.0", + "dev": true + }, + "ecc-jsbn": { + "version": "0.1.2", + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + }, + "dependencies": { + "jsbn": { + "version": "0.1.1" + } + } + }, + "ee-first": { + "version": "1.1.1" + }, + "electron-fetch": { + "version": "1.9.1", + "requires": { + "encoding": "^0.1.13" + } + }, + "electron-to-chromium": { + "version": "1.4.284", + "dev": true + }, + "elliptic": { + "version": "6.5.4", + "requires": { + "bn.js": "^4.11.9", + "brorand": "^1.1.0", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0" + } + } + }, + "emoji-regex": { + "version": "9.2.2", + "dev": true + }, + "emojis-list": { + "version": "3.0.0", + "dev": true + }, + "enabled": { + "version": "2.0.0" + }, + "encodeurl": { + "version": "1.0.2" + }, + "encoding": { + "version": "0.1.13", + "requires": { + "iconv-lite": "^0.6.2" + }, + "dependencies": { + "iconv-lite": { + "version": "0.6.3", + "requires": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + } + } + } + }, + "encoding-down": { + "version": "7.1.0", + "dev": true, + "requires": { + "abstract-leveldown": "^7.2.0", + "inherits": "^2.0.3", + "level-codec": "^10.0.0", + "level-errors": "^3.0.0" + } + }, + "end-of-stream": { + "version": "1.4.4", + "dev": true, + "requires": { + "once": "^1.4.0" + } + }, + "engine.io": { + "version": "6.2.0", + "dev": true, + "requires": { + "@types/cookie": "^0.4.1", + "@types/cors": "^2.8.12", + "@types/node": ">=10.0.0", + "accepts": "~1.3.4", + "base64id": "2.0.0", + "cookie": "~0.4.1", + "cors": "~2.8.5", + "debug": "~4.3.1", + "engine.io-parser": "~5.0.3", + "ws": "~8.2.3" + }, + "dependencies": { + "ws": { + "version": "8.2.3", + "dev": true, + "requires": {} + } + } + }, + "engine.io-parser": { + "version": "5.0.4", + "dev": true + }, + "enhanced-resolve": { + "version": "5.10.0", + "dev": true, + "requires": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + } + }, + "ent": { + "version": "2.2.0", + "dev": true + }, + "env-string": { + "version": "1.0.1", + "dev": true + }, + "envinfo": { + "version": "7.8.1", + "dev": true + }, + "err-code": { + "version": "2.0.3" + }, + "error-ex": { + "version": "1.3.2", + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "es-abstract": { + "version": "1.20.4", + "requires": { + "call-bind": "^1.0.2", + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "function.prototype.name": "^1.1.5", + "get-intrinsic": "^1.1.3", + "get-symbol-description": "^1.0.0", + "has": "^1.0.3", + "has-property-descriptors": "^1.0.0", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.3", + "is-callable": "^1.2.7", + "is-negative-zero": "^2.0.2", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "is-string": "^1.0.7", + "is-weakref": "^1.0.2", + "object-inspect": "^1.12.2", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.4.3", + "safe-regex-test": "^1.0.0", + "string.prototype.trimend": "^1.0.5", + "string.prototype.trimstart": "^1.0.5", + "unbox-primitive": "^1.0.2" + } + }, + "es-get-iterator": { + "version": "1.1.2", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.0", + "has-symbols": "^1.0.1", + "is-arguments": "^1.1.0", + "is-map": "^2.0.2", + "is-set": "^2.0.2", + "is-string": "^1.0.5", + "isarray": "^2.0.5" + }, + "dependencies": { + "isarray": { + "version": "2.0.5", + "dev": true + } + } + }, + "es-module-lexer": { + "version": "0.9.3", + "dev": true + }, + "es-shim-unscopables": { + "version": "1.0.0", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "es-to-primitive": { + "version": "1.2.1", + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "es5-ext": { + "version": "0.10.62", + "dev": true, + "requires": { + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.3", + "next-tick": "^1.1.0" + } + }, + "es6-error": { + "version": "4.1.1", + "dev": true + }, + "es6-iterator": { + "version": "2.0.3", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, + "es6-map": { + "version": "0.1.5", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "~0.10.14", + "es6-iterator": "~2.0.1", + "es6-set": "~0.1.5", + "es6-symbol": "~3.1.1", + "event-emitter": "~0.3.5" + } + }, + "es6-object-assign": { + "version": "1.1.0", + "dev": true + }, + "es6-promise": { + "version": "4.2.8" + }, + "es6-promisify": { + "version": "5.0.0", + "requires": { + "es6-promise": "^4.0.3" + } + }, + "es6-set": { + "version": "0.1.6", + "dev": true, + "requires": { + "d": "^1.0.1", + "es5-ext": "^0.10.62", + "es6-iterator": "~2.0.3", + "es6-symbol": "^3.1.3", + "event-emitter": "^0.3.5", + "type": "^2.7.2" + }, + "dependencies": { + "type": { + "version": "2.7.2", + "dev": true + } + } + }, + "es6-symbol": { + "version": "3.1.3", + "dev": true, + "requires": { + "d": "^1.0.1", + "ext": "^1.1.2" + } + }, + "es6-weak-map": { + "version": "2.0.3", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "^0.10.46", + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.1" + } + }, + "escalade": { + "version": "3.1.1" + }, + "escape-html": { + "version": "1.0.3" + }, + "escape-string-regexp": { + "version": "1.0.5", + "dev": true + }, + "escope": { + "version": "3.6.0", + "dev": true, + "requires": { + "es6-map": "^0.1.3", + "es6-weak-map": "^2.0.1", + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "eslint": { + "version": "8.22.0", + "dev": true, + "requires": { + "@eslint/eslintrc": "^1.3.0", + "@humanwhocodes/config-array": "^0.10.4", + "@humanwhocodes/gitignore-to-minimatch": "^1.0.2", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.1.1", + "eslint-utils": "^3.0.0", + "eslint-visitor-keys": "^3.3.0", + "espree": "^9.3.3", + "esquery": "^1.4.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^6.0.1", + "globals": "^13.15.0", + "globby": "^11.1.0", + "grapheme-splitter": "^1.0.4", + "ignore": "^5.2.0", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "regexpp": "^3.2.0", + "strip-ansi": "^6.0.1", + "strip-json-comments": "^3.1.0", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + }, + "dependencies": { + "escape-string-regexp": { + "version": "4.0.0", + "dev": true + }, + "eslint-scope": { + "version": "7.1.1", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + } + }, + "estraverse": { + "version": "5.3.0", + "dev": true + } + } + }, + "eslint-config-prettier": { + "version": "8.5.0", + "dev": true, + "requires": {} + }, + "eslint-config-standard": { + "version": "10.2.1", + "dev": true, + "requires": {} + }, + "eslint-config-typestrict": { + "version": "1.0.5", + "dev": true, + "requires": {} + }, + "eslint-formatter-codeframe": { + "version": "7.32.1", + "dev": true, + "requires": { + "@babel/code-frame": "7.12.11", + "chalk": "^4.0.0" + } + }, + "eslint-import-resolver-node": { + "version": "0.3.6", + "dev": true, + "requires": { + "debug": "^3.2.7", + "resolve": "^1.20.0" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.3", + "dev": true + } + } + }, + "eslint-module-utils": { + "version": "2.7.4", + "dev": true, + "requires": { + "debug": "^3.2.7" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.3", + "dev": true + } + } + }, + "eslint-plugin-escompat": { + "version": "3.3.4", + "dev": true, + "requires": { + "browserslist": "^4.21.0" + } + }, + "eslint-plugin-eslint-comments": { + "version": "3.2.0", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5", + "ignore": "^5.0.5" + } + }, + "eslint-plugin-ethereumjs": { + "version": "file:eslint" + }, + "eslint-plugin-filenames": { + "version": "1.3.2", + "dev": true, + "requires": { + "lodash.camelcase": "4.3.0", + "lodash.kebabcase": "4.1.1", + "lodash.snakecase": "4.1.1", + "lodash.upperfirst": "4.3.1" + } + }, + "eslint-plugin-github": { + "version": "4.3.7", + "dev": true, + "requires": { + "@typescript-eslint/eslint-plugin": "^5.1.0", + "@typescript-eslint/parser": "^5.1.0", + "eslint-config-prettier": ">=8.0.0", + "eslint-plugin-escompat": "^3.1.0", + "eslint-plugin-eslint-comments": "^3.2.0", + "eslint-plugin-filenames": "^1.3.2", + "eslint-plugin-i18n-text": "^1.0.1", + "eslint-plugin-import": "^2.25.2", + "eslint-plugin-jsx-a11y": "^6.6.0", + "eslint-plugin-no-only-tests": "^2.6.0", + "eslint-plugin-prettier": "^4.0.0", + "eslint-rule-documentation": ">=1.0.0", + "jsx-ast-utils": "^3.3.2", + "prettier": "^2.2.1", + "svg-element-attributes": "^1.3.1" + } + }, + "eslint-plugin-i18n-text": { + "version": "1.0.1", + "dev": true, + "requires": {} + }, + "eslint-plugin-implicit-dependencies": { + "version": "1.1.1", + "dev": true, + "requires": { + "builtin-modules": "^1.1.1", + "findup": "^0.1.5" + } + }, + "eslint-plugin-import": { + "version": "2.26.0", + "dev": true, + "requires": { + "array-includes": "^3.1.4", + "array.prototype.flat": "^1.2.5", + "debug": "^2.6.9", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.6", + "eslint-module-utils": "^2.7.3", + "has": "^1.0.3", + "is-core-module": "^2.8.1", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.values": "^1.1.5", + "resolve": "^1.22.0", + "tsconfig-paths": "^3.14.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "doctrine": { + "version": "2.1.0", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "ms": { + "version": "2.0.0", + "dev": true + } + } + }, + "eslint-plugin-jsx-a11y": { + "version": "6.6.1", + "dev": true, + "requires": { + "@babel/runtime": "^7.18.9", + "aria-query": "^4.2.2", + "array-includes": "^3.1.5", + "ast-types-flow": "^0.0.7", + "axe-core": "^4.4.3", + "axobject-query": "^2.2.0", + "damerau-levenshtein": "^1.0.8", + "emoji-regex": "^9.2.2", + "has": "^1.0.3", + "jsx-ast-utils": "^3.3.2", + "language-tags": "^1.0.5", + "minimatch": "^3.1.2", + "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "dev": true + } + } + }, + "eslint-plugin-no-only-tests": { + "version": "2.6.0", + "dev": true + }, + "eslint-plugin-node": { + "version": "4.2.3", + "dev": true, + "requires": { + "ignore": "^3.0.11", + "minimatch": "^3.0.2", + "object-assign": "^4.0.1", + "resolve": "^1.1.7", + "semver": "5.3.0" + }, + "dependencies": { + "ignore": { + "version": "3.3.10", + "dev": true + }, + "semver": { + "version": "5.3.0", + "dev": true + } + } + }, + "eslint-plugin-prettier": { + "version": "4.2.1", + "dev": true, + "requires": { + "prettier-linter-helpers": "^1.0.0" + } + }, + "eslint-plugin-promise": { + "version": "3.5.0", + "dev": true + }, + "eslint-plugin-simple-import-sort": { + "version": "7.0.0", + "dev": true, + "requires": {} + }, + "eslint-plugin-sonarjs": { + "version": "0.14.0", + "dev": true, + "requires": {} + }, + "eslint-plugin-standard": { + "version": "3.0.1", + "dev": true, + "requires": {} + }, + "eslint-rule-documentation": { + "version": "1.0.23", + "dev": true + }, + "eslint-scope": { + "version": "5.1.1", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + } + }, + "eslint-utils": { + "version": "3.0.0", + "dev": true, + "requires": { + "eslint-visitor-keys": "^2.0.0" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "2.1.0", + "dev": true + } + } + }, + "eslint-visitor-keys": { + "version": "3.3.0", + "dev": true + }, + "espree": { + "version": "9.4.0", + "dev": true, + "requires": { + "acorn": "^8.8.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.3.0" + } + }, + "esprima": { + "version": "4.0.1", + "dev": true + }, + "esquery": { + "version": "1.4.0", + "dev": true, + "requires": { + "estraverse": "^5.1.0" + }, + "dependencies": { + "estraverse": { + "version": "5.3.0", + "dev": true + } + } + }, + "esrecurse": { + "version": "4.3.0", + "dev": true, + "requires": { + "estraverse": "^5.2.0" + }, + "dependencies": { + "estraverse": { + "version": "5.3.0", + "dev": true + } + } + }, + "estraverse": { + "version": "4.3.0", + "dev": true + }, + "estree-is-member-expression": { + "version": "1.0.0", + "dev": true + }, + "esutils": { + "version": "2.0.3", + "dev": true + }, + "ethereum-cryptography": { + "version": "2.0.0", + "requires": { + "@noble/curves": "1.0.0", + "@noble/hashes": "1.3.0", + "@scure/bip32": "1.3.0", + "@scure/bip39": "1.2.0" + } + }, + "ethers": { + "version": "5.7.2", + "requires": { + "@ethersproject/abi": "5.7.0", + "@ethersproject/abstract-provider": "5.7.0", + "@ethersproject/abstract-signer": "5.7.0", + "@ethersproject/address": "5.7.0", + "@ethersproject/base64": "5.7.0", + "@ethersproject/basex": "5.7.0", + "@ethersproject/bignumber": "5.7.0", + "@ethersproject/bytes": "5.7.0", + "@ethersproject/constants": "5.7.0", + "@ethersproject/contracts": "5.7.0", + "@ethersproject/hash": "5.7.0", + "@ethersproject/hdnode": "5.7.0", + "@ethersproject/json-wallets": "5.7.0", + "@ethersproject/keccak256": "5.7.0", + "@ethersproject/logger": "5.7.0", + "@ethersproject/networks": "5.7.1", + "@ethersproject/pbkdf2": "5.7.0", + "@ethersproject/properties": "5.7.0", + "@ethersproject/providers": "5.7.2", + "@ethersproject/random": "5.7.0", + "@ethersproject/rlp": "5.7.0", + "@ethersproject/sha2": "5.7.0", + "@ethersproject/signing-key": "5.7.0", + "@ethersproject/solidity": "5.7.0", + "@ethersproject/strings": "5.7.0", + "@ethersproject/transactions": "5.7.0", + "@ethersproject/units": "5.7.0", + "@ethersproject/wallet": "5.7.0", + "@ethersproject/web": "5.7.1", + "@ethersproject/wordlists": "5.7.0" + } + }, + "event-emitter": { + "version": "0.3.5", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "~0.10.14" + } + }, + "event-iterator": { + "version": "2.0.0" + }, + "event-target-shim": { + "version": "5.0.1" + }, + "eventemitter3": { + "version": "4.0.7" + }, + "events": { + "version": "2.1.0", + "dev": true + }, + "evp_bytestokey": { + "version": "1.0.3", + "dev": true, + "requires": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, + "execa": { + "version": "5.1.1", + "requires": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + } + }, + "execspawn": { + "version": "1.0.1", + "dev": true, + "requires": { + "util-extend": "^1.0.1" + } + }, + "exit-hook": { + "version": "1.1.1", + "dev": true + }, + "ext": { + "version": "1.7.0", + "dev": true, + "requires": { + "type": "^2.7.2" + }, + "dependencies": { + "type": { + "version": "2.7.2", + "dev": true + } + } + }, + "extend": { + "version": "3.0.2" + }, + "extsprintf": { + "version": "1.3.0" + }, + "eyes": { + "version": "0.1.8" + }, + "fast-deep-equal": { + "version": "3.1.3" + }, + "fast-diff": { + "version": "1.2.0", + "dev": true + }, + "fast-fifo": { + "version": "1.1.0" + }, + "fast-glob": { + "version": "3.2.12", + "dev": true, + "requires": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "dependencies": { + "glob-parent": { + "version": "5.1.2", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + } + } + }, + "fast-json-stable-stringify": { + "version": "2.1.0" + }, + "fast-levenshtein": { + "version": "2.0.6", + "dev": true + }, + "fast-redact": { + "version": "2.1.0", + "dev": true + }, + "fast-safe-stringify": { + "version": "2.1.1", + "dev": true + }, + "fastest-levenshtein": { + "version": "1.0.16", + "dev": true + }, + "fastq": { + "version": "1.13.0", + "dev": true, + "requires": { + "reusify": "^1.0.4" + } + }, + "fecha": { + "version": "4.2.3" + }, + "figures": { + "version": "1.7.0", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5", + "object-assign": "^4.1.0" + } + }, + "file-entry-cache": { + "version": "6.0.1", + "dev": true, + "requires": { + "flat-cache": "^3.0.4" + } + }, + "file-replace-loader": { + "version": "1.4.0", + "dev": true, + "requires": { + "loader-utils": "^2.0.0", + "schema-utils": "^2.7.1" + } + }, + "file-stream-rotator": { + "version": "0.6.1", + "requires": { + "moment": "^2.29.1" + } + }, + "file-uri-to-path": { + "version": "1.0.0" + }, + "fill-range": { + "version": "7.0.1", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "finalhandler": { + "version": "1.1.2", + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0" + }, + "on-finished": { + "version": "2.3.0", + "requires": { + "ee-first": "1.1.1" + } + } + } + }, + "find-cache-dir": { + "version": "3.3.2", + "dev": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^3.0.2", + "pkg-dir": "^4.1.0" + }, + "dependencies": { + "make-dir": { + "version": "3.1.0", + "dev": true, + "requires": { + "semver": "^6.0.0" + } + }, + "semver": { + "version": "6.3.0", + "dev": true + } + } + }, + "find-root": { + "version": "1.1.0", + "dev": true + }, + "find-up": { + "version": "5.0.0", + "dev": true, + "requires": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + } + }, + "findup": { + "version": "0.1.5", + "dev": true, + "requires": { + "colors": "~0.6.0-1", + "commander": "~2.1.0" + } + }, + "flat-cache": { + "version": "3.0.4", + "dev": true, + "requires": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + } + }, + "flatstr": { + "version": "1.0.12", + "dev": true + }, + "flatted": { + "version": "3.2.7", + "dev": true + }, + "fn.name": { + "version": "1.1.0" + }, + "follow-redirects": { + "version": "1.15.2", + "dev": true + }, + "for-each": { + "version": "0.3.3", + "requires": { + "is-callable": "^1.1.3" + } + }, + "foreground-child": { + "version": "2.0.0", + "dev": true, + "requires": { + "cross-spawn": "^7.0.0", + "signal-exit": "^3.0.2" + } + }, + "forever-agent": { + "version": "0.6.1" + }, + "form-data": { + "version": "2.3.3", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, + "formidable": { + "version": "2.0.1", + "dev": true, + "requires": { + "dezalgo": "1.0.3", + "hexoid": "1.0.0", + "once": "1.4.0", + "qs": "6.9.3" + }, + "dependencies": { + "qs": { + "version": "6.9.3", + "dev": true + } + } + }, + "fromentries": { + "version": "1.3.2", + "dev": true + }, + "fs-extra": { + "version": "10.1.0", + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "dev": true + }, + "function-bind": { + "version": "1.1.1" + }, + "function.prototype.name": { + "version": "1.1.5", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.0", + "functions-have-names": "^1.2.2" + } + }, + "functional-red-black-tree": { + "version": "1.0.1" + }, + "functions-have-names": { + "version": "1.2.3" + }, + "generate-function": { + "version": "2.3.1", + "dev": true, + "requires": { + "is-property": "^1.0.2" + } + }, + "generate-object-property": { + "version": "1.2.0", + "dev": true, + "requires": { + "is-property": "^1.0.0" + } + }, + "gensync": { + "version": "1.0.0-beta.2", + "dev": true + }, + "get-assigned-identifiers": { + "version": "1.2.0", + "dev": true + }, + "get-caller-file": { + "version": "2.0.5" + }, + "get-func-name": { + "version": "2.0.0" + }, + "get-intrinsic": { + "version": "1.1.3", + "requires": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.3" + } + }, + "get-iterator": { + "version": "1.0.2" + }, + "get-package-type": { + "version": "0.1.0", + "dev": true + }, + "get-stdin": { + "version": "5.0.1", + "dev": true + }, + "get-stream": { + "version": "6.0.1" + }, + "get-symbol-description": { + "version": "1.0.0", + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + } + }, + "getpass": { + "version": "0.1.7", + "requires": { + "assert-plus": "^1.0.0" + } + }, + "git-hooks-list": { + "version": "1.0.3", + "dev": true + }, + "glob": { + "version": "7.2.3", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-parent": { + "version": "6.0.2", + "dev": true, + "requires": { + "is-glob": "^4.0.3" + } + }, + "glob-to-regexp": { + "version": "0.4.1", + "dev": true + }, + "globals": { + "version": "13.17.0", + "dev": true, + "requires": { + "type-fest": "^0.20.2" + } + }, + "globby": { + "version": "11.1.0", + "dev": true, + "requires": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + } + }, + "graceful-fs": { + "version": "4.2.10" + }, + "grapheme-splitter": { + "version": "1.0.4", + "dev": true + }, + "handlebars": { + "version": "4.7.7", + "dev": true, + "requires": { + "minimist": "^1.2.5", + "neo-async": "^2.6.0", + "source-map": "^0.6.1", + "uglify-js": "^3.1.4", + "wordwrap": "^1.0.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "dev": true + } + } + }, + "har-schema": { + "version": "2.0.0" + }, + "har-validator": { + "version": "5.1.5", + "requires": { + "ajv": "^6.12.3", + "har-schema": "^2.0.0" + } + }, + "has": { + "version": "1.0.3", + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-ansi": { + "version": "2.0.0", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "dev": true + } + } + }, + "has-bigints": { + "version": "1.0.2" + }, + "has-dynamic-import": { + "version": "2.0.1", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + } + }, + "has-flag": { + "version": "4.0.0" + }, + "has-property-descriptors": { + "version": "1.0.0", + "requires": { + "get-intrinsic": "^1.1.1" + } + }, + "has-symbols": { + "version": "1.0.3" + }, + "has-tostringtag": { + "version": "1.0.0", + "requires": { + "has-symbols": "^1.0.2" + } + }, + "has-unicode": { + "version": "2.0.1", + "dev": true + }, + "hash-base": { + "version": "3.1.0", + "dev": true, + "requires": { + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "hash.js": { + "version": "1.1.7", + "requires": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "hasha": { + "version": "5.2.2", + "dev": true, + "requires": { + "is-stream": "^2.0.0", + "type-fest": "^0.8.0" + }, + "dependencies": { + "type-fest": { + "version": "0.8.1", + "dev": true + } + } + }, + "hashlru": { + "version": "2.3.0" + }, + "heap": { + "version": "0.2.7" + }, + "hexoid": { + "version": "1.0.0", + "dev": true + }, + "hmac-drbg": { + "version": "1.0.1", + "requires": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "hsl-to-rgb-for-reals": { + "version": "1.1.1", + "dev": true + }, + "html-escaper": { + "version": "2.0.2", + "dev": true + }, + "htmlescape": { + "version": "1.1.1", + "dev": true + }, + "http-errors": { + "version": "2.0.0", + "requires": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "dependencies": { + "statuses": { + "version": "2.0.1" + } + } + }, + "http-proxy": { + "version": "1.18.1", + "dev": true, + "requires": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + } + }, + "http-signature": { + "version": "1.2.0", + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "https-browserify": { + "version": "1.0.0", + "dev": true + }, + "human-signals": { + "version": "2.1.0" + }, + "hyperscript-attribute-to-property": { + "version": "1.0.2", + "dev": true + }, + "hyperx": { + "version": "2.5.4", + "dev": true, + "requires": { + "hyperscript-attribute-to-property": "^1.0.0" + } + }, + "iconv-lite": { + "version": "0.4.24", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ieee754": { + "version": "1.2.1" + }, + "ignore": { + "version": "5.2.0", + "dev": true + }, + "import-fresh": { + "version": "3.3.0", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "import-local": { + "version": "3.1.0", + "dev": true, + "requires": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "dev": true + }, + "indent-string": { + "version": "4.0.0" + }, + "inflight": { + "version": "1.0.6", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4" + }, + "inline-source-map": { + "version": "0.6.2", + "dev": true, + "requires": { + "source-map": "~0.5.3" + } + }, + "inquirer": { + "version": "0.12.0", + "dev": true, + "requires": { + "ansi-escapes": "^1.1.0", + "ansi-regex": "^2.0.0", + "chalk": "^1.0.0", + "cli-cursor": "^1.0.1", + "cli-width": "^2.0.0", + "figures": "^1.3.5", + "lodash": "^4.3.0", + "readline2": "^1.0.1", + "run-async": "^0.1.0", + "rx-lite": "^3.1.2", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.0", + "through": "^2.3.6" + }, + "dependencies": { + "ansi-escapes": { + "version": "1.4.0", + "dev": true + }, + "ansi-regex": { + "version": "2.1.1", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "cli-cursor": { + "version": "1.0.2", + "dev": true, + "requires": { + "restore-cursor": "^1.0.1" + } + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "onetime": { + "version": "1.1.0", + "dev": true + }, + "restore-cursor": { + "version": "1.0.1", + "dev": true, + "requires": { + "exit-hook": "^1.0.0", + "onetime": "^1.0.0" + } + }, + "string-width": { + "version": "1.0.2", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "dev": true + } + } + }, + "insert-module-globals": { + "version": "7.2.1", + "dev": true, + "requires": { + "acorn-node": "^1.5.2", + "combine-source-map": "^0.8.0", + "concat-stream": "^1.6.1", + "is-buffer": "^1.1.0", + "JSONStream": "^1.0.3", + "path-is-absolute": "^1.0.1", + "process": "~0.11.0", + "through2": "^2.0.0", + "undeclared-identifiers": "^1.1.2", + "xtend": "^4.0.0" + }, + "dependencies": { + "is-buffer": { + "version": "1.1.6", + "dev": true + } + } + }, + "interface-datastore": { + "version": "3.0.6", + "requires": { + "err-code": "^3.0.1", + "ipfs-utils": "^6.0.0", + "iso-random-stream": "^2.0.0", + "it-all": "^1.0.2", + "it-drain": "^1.0.1", + "nanoid": "^3.0.2" + }, + "dependencies": { + "err-code": { + "version": "3.0.1" + } + } + }, + "internal-slot": { + "version": "1.0.3", + "requires": { + "get-intrinsic": "^1.1.0", + "has": "^1.0.3", + "side-channel": "^1.0.4" + } + }, + "internmap": { + "version": "1.0.1", + "dev": true + }, + "interpret": { + "version": "2.2.0", + "dev": true + }, + "ip-address": { + "version": "6.4.0", + "requires": { + "jsbn": "1.1.0", + "lodash.find": "4.6.0", + "lodash.max": "4.0.1", + "lodash.merge": "4.6.2", + "lodash.padstart": "4.6.1", + "lodash.repeat": "4.1.0", + "sprintf-js": "1.1.2" + } + }, + "ip-regex": { + "version": "4.3.0" + }, + "ipaddr.js": { + "version": "2.0.1" + }, + "ipfs-utils": { + "version": "6.0.8", + "requires": { + "abort-controller": "^3.0.0", + "any-signal": "^2.1.0", + "buffer": "^6.0.1", + "electron-fetch": "^1.7.2", + "err-code": "^3.0.1", + "is-electron": "^2.2.0", + "iso-url": "^1.0.0", + "it-glob": "~0.0.11", + "it-to-stream": "^1.0.0", + "merge-options": "^3.0.4", + "nanoid": "^3.1.20", + "native-abort-controller": "^1.0.3", + "native-fetch": "^3.0.0", + "node-fetch": "^2.6.1", + "stream-to-it": "^0.2.2" + }, + "dependencies": { + "err-code": { + "version": "3.0.1" + } + } + }, + "is-arguments": { + "version": "1.1.1", + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } + }, + "is-arrayish": { + "version": "0.2.1", + "dev": true + }, + "is-bigint": { + "version": "1.0.4", + "requires": { + "has-bigints": "^1.0.1" + } + }, + "is-binary-path": { + "version": "2.1.0", + "dev": true, + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-boolean-attribute": { + "version": "0.0.1", + "dev": true + }, + "is-boolean-object": { + "version": "1.1.2", + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } + }, + "is-buffer": { + "version": "2.0.5" + }, + "is-callable": { + "version": "1.2.7" + }, + "is-core-module": { + "version": "2.11.0", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "is-date-object": { + "version": "1.0.5", + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-docker": { + "version": "2.2.1", + "dev": true + }, + "is-electron": { + "version": "2.2.1" + }, + "is-extglob": { + "version": "2.1.1", + "dev": true + }, + "is-fn": { + "version": "1.0.0" + }, + "is-fullwidth-code-point": { + "version": "4.0.0", + "dev": true + }, + "is-generator-function": { + "version": "1.0.10", + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-glob": { + "version": "4.0.3", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-ip": { + "version": "3.1.0", + "requires": { + "ip-regex": "^4.0.0" + } + }, + "is-loopback-addr": { + "version": "1.0.1" + }, + "is-map": { + "version": "2.0.2", + "dev": true + }, + "is-my-ip-valid": { + "version": "1.0.1", + "dev": true + }, + "is-my-json-valid": { + "version": "2.20.6", + "dev": true, + "requires": { + "generate-function": "^2.0.0", + "generate-object-property": "^1.1.0", + "is-my-ip-valid": "^1.0.0", + "jsonpointer": "^5.0.0", + "xtend": "^4.0.0" + } + }, + "is-nan": { + "version": "1.3.2", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3" + } + }, + "is-negative-zero": { + "version": "2.0.2" + }, + "is-number": { + "version": "7.0.0", + "dev": true + }, + "is-number-object": { + "version": "1.0.7", + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-plain-obj": { + "version": "2.1.0" + }, + "is-plain-object": { + "version": "2.0.4", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + }, + "is-property": { + "version": "1.0.2", + "dev": true + }, + "is-regex": { + "version": "1.1.4", + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } + }, + "is-regexp": { + "version": "1.0.0", + "dev": true + }, + "is-resolvable": { + "version": "1.1.0", + "dev": true + }, + "is-set": { + "version": "2.0.2", + "dev": true + }, + "is-shared-array-buffer": { + "version": "1.0.2", + "requires": { + "call-bind": "^1.0.2" + } + }, + "is-stream": { + "version": "2.0.1" + }, + "is-string": { + "version": "1.0.7", + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-symbol": { + "version": "1.0.4", + "requires": { + "has-symbols": "^1.0.2" + } + }, + "is-typed-array": { + "version": "1.1.9", + "requires": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "es-abstract": "^1.20.0", + "for-each": "^0.3.3", + "has-tostringtag": "^1.0.0" + } + }, + "is-typedarray": { + "version": "1.0.0" + }, + "is-weakmap": { + "version": "2.0.1", + "dev": true + }, + "is-weakref": { + "version": "1.0.2", + "requires": { + "call-bind": "^1.0.2" + } + }, + "is-weakset": { + "version": "2.0.2", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + } + }, + "is-windows": { + "version": "1.0.2", + "dev": true + }, + "is-wsl": { + "version": "2.2.0", + "dev": true, + "requires": { + "is-docker": "^2.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "dev": true + }, + "isbinaryfile": { + "version": "4.0.10", + "dev": true + }, + "isexe": { + "version": "2.0.0" + }, + "iso-random-stream": { + "version": "2.0.2", + "requires": { + "events": "^3.3.0", + "readable-stream": "^3.4.0" + }, + "dependencies": { + "events": { + "version": "3.3.0" + }, + "readable-stream": { + "version": "3.6.0", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "iso-url": { + "version": "1.2.1" + }, + "isobject": { + "version": "3.0.1", + "dev": true + }, + "isomorphic-ws": { + "version": "4.0.1", + "requires": {} + }, + "isstream": { + "version": "0.1.2" + }, + "istanbul-lib-coverage": { + "version": "3.2.0", + "dev": true + }, + "istanbul-lib-hook": { + "version": "3.0.0", + "dev": true, + "requires": { + "append-transform": "^2.0.0" + } + }, + "istanbul-lib-instrument": { + "version": "4.0.3", + "dev": true, + "requires": { + "@babel/core": "^7.7.5", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.0.0", + "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "dev": true + } + } + }, + "istanbul-lib-processinfo": { + "version": "2.0.3", + "dev": true, + "requires": { + "archy": "^1.0.0", + "cross-spawn": "^7.0.3", + "istanbul-lib-coverage": "^3.2.0", + "p-map": "^3.0.0", + "rimraf": "^3.0.0", + "uuid": "^8.3.2" + }, + "dependencies": { + "p-map": { + "version": "3.0.0", + "dev": true, + "requires": { + "aggregate-error": "^3.0.0" + } + } + } + }, + "istanbul-lib-report": { + "version": "3.0.0", + "dev": true, + "requires": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^3.0.0", + "supports-color": "^7.1.0" + }, + "dependencies": { + "make-dir": { + "version": "3.1.0", + "dev": true, + "requires": { + "semver": "^6.0.0" + } + }, + "semver": { + "version": "6.3.0", + "dev": true + } + } + }, + "istanbul-lib-source-maps": { + "version": "4.0.1", + "dev": true, + "requires": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "dev": true + } + } + }, + "istanbul-reports": { + "version": "3.1.5", + "dev": true, + "requires": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + } + }, + "it-all": { + "version": "1.0.6" + }, + "it-buffer": { + "version": "0.1.3", + "requires": { + "bl": "^5.0.0", + "buffer": "^6.0.3" + }, + "dependencies": { + "bl": { + "version": "5.1.0", + "requires": { + "buffer": "^6.0.3", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "readable-stream": { + "version": "3.6.0", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "it-drain": { + "version": "1.0.5" + }, + "it-filter": { + "version": "1.0.3" + }, + "it-first": { + "version": "1.0.7" + }, + "it-glob": { + "version": "0.0.14", + "requires": { + "@types/minimatch": "^3.0.4", + "minimatch": "^3.0.4" + } + }, + "it-goodbye": { + "version": "2.0.2", + "requires": { + "buffer": "^5.6.0" + }, + "dependencies": { + "buffer": { + "version": "5.7.1", + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + } + } + }, + "it-handshake": { + "version": "2.0.0", + "requires": { + "it-pushable": "^1.4.0", + "it-reader": "^3.0.0", + "p-defer": "^3.0.0" + } + }, + "it-length-prefixed": { + "version": "5.0.3", + "requires": { + "bl": "^5.0.0", + "buffer": "^6.0.3", + "varint": "^6.0.0" + }, + "dependencies": { + "bl": { + "version": "5.1.0", + "requires": { + "buffer": "^6.0.3", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "readable-stream": { + "version": "3.6.0", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "it-map": { + "version": "1.0.6" + }, + "it-merge": { + "version": "1.0.0", + "requires": { + "it-pushable": "^1.4.0" + } + }, + "it-pair": { + "version": "1.0.0", + "requires": { + "get-iterator": "^1.0.2" + } + }, + "it-pb-rpc": { + "version": "0.1.13", + "requires": { + "is-buffer": "^2.0.5", + "it-handshake": "^2.0.0", + "it-length-prefixed": "^5.0.2" + } + }, + "it-pipe": { + "version": "1.1.0" + }, + "it-protocol-buffers": { + "version": "0.2.1", + "requires": { + "it-buffer": "^0.1.1", + "it-length-prefixed": "^3.0.0" + }, + "dependencies": { + "bl": { + "version": "4.1.0", + "requires": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "buffer": { + "version": "5.7.1", + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "it-length-prefixed": { + "version": "3.1.0", + "requires": { + "@types/bl": "^2.1.0", + "bl": "^4.0.2", + "buffer": "^5.5.0", + "varint": "^5.0.0" + } + }, + "readable-stream": { + "version": "3.6.0", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "varint": { + "version": "5.0.2" + } + } + }, + "it-pushable": { + "version": "1.4.2", + "requires": { + "fast-fifo": "^1.0.0" + } + }, + "it-reader": { + "version": "3.0.0", + "requires": { + "bl": "^5.0.0" + }, + "dependencies": { + "bl": { + "version": "5.1.0", + "requires": { + "buffer": "^6.0.3", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "readable-stream": { + "version": "3.6.0", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "it-take": { + "version": "1.0.0" + }, + "it-to-stream": { + "version": "1.0.0", + "requires": { + "buffer": "^6.0.3", + "fast-fifo": "^1.0.0", + "get-iterator": "^1.0.2", + "p-defer": "^3.0.0", + "p-fifo": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "it-ws": { + "version": "4.0.0", + "requires": { + "buffer": "^6.0.3", + "event-iterator": "^2.0.0", + "iso-url": "^1.1.2", + "ws": "^7.3.1" + } + }, + "jayson": { + "version": "4.0.0", + "requires": { + "@types/connect": "^3.4.33", + "@types/node": "^12.12.54", + "@types/ws": "^7.4.4", + "commander": "^2.20.3", + "delay": "^5.0.0", + "es6-promisify": "^5.0.0", + "eyes": "^0.1.8", + "isomorphic-ws": "^4.0.1", + "json-stringify-safe": "^5.0.1", + "JSONStream": "^1.3.5", + "uuid": "^8.3.2", + "ws": "^7.4.5" + }, + "dependencies": { + "@types/node": { + "version": "12.20.55" + }, + "commander": { + "version": "2.20.3" + } + } + }, + "jest-worker": { + "version": "27.5.1", + "dev": true, + "requires": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "dependencies": { + "supports-color": { + "version": "8.1.1", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "js-sdsl": { + "version": "4.1.5" + }, + "js-sha3": { + "version": "0.8.0" + }, + "js-tokens": { + "version": "4.0.0", + "dev": true + }, + "js-yaml": { + "version": "4.1.0", + "dev": true, + "requires": { + "argparse": "^2.0.1" + } + }, + "jsbn": { + "version": "1.1.0" + }, + "jsesc": { + "version": "2.5.2", + "dev": true + }, + "json-parse-better-errors": { + "version": "1.0.2", + "dev": true + }, + "json-parse-even-better-errors": { + "version": "2.3.1", + "dev": true + }, + "json-schema": { + "version": "0.4.0" + }, + "json-schema-traverse": { + "version": "0.4.1" + }, + "json-stable-stringify": { + "version": "0.0.1", + "dev": true, + "requires": { + "jsonify": "~0.0.0" + } + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "dev": true + }, + "json-stringify-safe": { + "version": "5.0.1" + }, + "json5": { + "version": "2.2.1", + "dev": true + }, + "jsonc-parser": { + "version": "3.2.0", + "dev": true + }, + "jsonfile": { + "version": "6.1.0", + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "jsonify": { + "version": "0.0.1", + "dev": true + }, + "jsonparse": { + "version": "1.3.1" + }, + "jsonpointer": { + "version": "5.0.1", + "dev": true + }, + "JSONStream": { + "version": "1.3.5", + "requires": { + "jsonparse": "^1.2.0", + "through": ">=2.2.7 <3" + } + }, + "jsonstream2": { + "version": "1.1.2", + "dev": true, + "requires": { + "jsonparse": "0.0.6", + "through2": "^0.6.1", + "type-component": "0.0.1" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "dev": true + }, + "jsonparse": { + "version": "0.0.6", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "string_decoder": { + "version": "0.10.31", + "dev": true + }, + "through2": { + "version": "0.6.5", + "dev": true, + "requires": { + "readable-stream": ">=1.0.33-1 <1.1.0-0", + "xtend": ">=4.0.0 <4.1.0-0" + } + } + } + }, + "jsprim": { + "version": "1.4.2", + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.4.0", + "verror": "1.10.0" + } + }, + "jsx-ast-utils": { + "version": "3.3.3", + "dev": true, + "requires": { + "array-includes": "^3.1.5", + "object.assign": "^4.1.3" + } + }, + "just-extend": { + "version": "4.2.1" + }, + "jwt-simple": { + "version": "0.5.6" + }, + "k-bucket": { + "version": "5.1.0", + "requires": { + "randombytes": "^2.1.0" + } + }, + "karma": { + "version": "6.4.0", + "dev": true, + "requires": { + "@colors/colors": "1.5.0", + "body-parser": "^1.19.0", + "braces": "^3.0.2", + "chokidar": "^3.5.1", + "connect": "^3.7.0", + "di": "^0.0.1", + "dom-serialize": "^2.2.1", + "glob": "^7.1.7", + "graceful-fs": "^4.2.6", + "http-proxy": "^1.18.1", + "isbinaryfile": "^4.0.8", + "lodash": "^4.17.21", + "log4js": "^6.4.1", + "mime": "^2.5.2", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.5", + "qjobs": "^1.2.0", + "range-parser": "^1.2.1", + "rimraf": "^3.0.2", + "socket.io": "^4.4.1", + "source-map": "^0.6.1", + "tmp": "^0.2.1", + "ua-parser-js": "^0.7.30", + "yargs": "^16.1.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "dev": true + } + } + }, + "karma-chrome-launcher": { + "version": "3.1.1", + "dev": true, + "requires": { + "which": "^1.2.1" + } + }, + "karma-firefox-launcher": { + "version": "2.1.2", + "dev": true, + "requires": { + "is-wsl": "^2.2.0", + "which": "^2.0.1" + }, + "dependencies": { + "which": { + "version": "2.0.2", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "karma-tap": { + "version": "4.2.0", + "dev": true, + "requires": { + "babel-polyfill": "^6.26.0" + } + }, + "karma-typescript": { + "version": "5.5.3", + "dev": true, + "requires": { + "acorn": "^8.1.0", + "acorn-walk": "^8.0.2", + "assert": "^2.0.0", + "async": "^3.0.1", + "browser-resolve": "^2.0.0", + "browserify-zlib": "^0.2.0", + "buffer": "^5.4.3", + "combine-source-map": "^0.8.0", + "console-browserify": "^1.2.0", + "constants-browserify": "^1.0.0", + "convert-source-map": "^1.7.0", + "crypto-browserify": "^3.12.0", + "diff": "^4.0.1", + "domain-browser": "^4.16.0", + "events": "^3.2.0", + "glob": "^7.1.6", + "https-browserify": "^1.0.0", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^4.0.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.0.0", + "json-stringify-safe": "^5.0.1", + "lodash": "^4.17.19", + "log4js": "^6.3.0", + "minimatch": "^3.0.4", + "os-browserify": "^0.3.0", + "pad": "^3.2.0", + "path-browserify": "^1.0.0", + "process": "^0.11.10", + "punycode": "^2.1.1", + "querystring-es3": "^0.2.1", + "readable-stream": "^3.1.1", + "source-map": "^0.7.3", + "stream-browserify": "^3.0.0", + "stream-http": "^3.1.0", + "string_decoder": "^1.3.0", + "timers-browserify": "^2.0.11", + "tmp": "^0.2.1", + "tty-browserify": "^0.0.1", + "url": "^0.11.0", + "util": "^0.12.1", + "vm-browserify": "^1.1.2" + }, + "dependencies": { + "acorn-walk": { + "version": "8.2.0", + "dev": true + }, + "assert": { + "version": "2.0.0", + "dev": true, + "requires": { + "es6-object-assign": "^1.1.0", + "is-nan": "^1.2.1", + "object-is": "^1.0.1", + "util": "^0.12.0" + } + }, + "buffer": { + "version": "5.7.1", + "dev": true, + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "convert-source-map": { + "version": "1.9.0", + "dev": true + }, + "domain-browser": { + "version": "4.22.0", + "dev": true + }, + "events": { + "version": "3.3.0", + "dev": true + }, + "path-browserify": { + "version": "1.0.1", + "dev": true + }, + "punycode": { + "version": "2.1.1", + "dev": true + }, + "readable-stream": { + "version": "3.6.0", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "source-map": { + "version": "0.7.4", + "dev": true + }, + "timers-browserify": { + "version": "2.0.12", + "dev": true, + "requires": { + "setimmediate": "^1.0.4" + } + } + } + }, + "karma-typescript-es6-transform": { + "version": "5.5.3", + "dev": true, + "requires": { + "@babel/core": "^7.11.1", + "@babel/preset-env": "^7.11.0", + "acorn": "^8.1.0", + "acorn-walk": "^8.0.2", + "log4js": "^6.3.0", + "magic-string": "^0.25.7" + }, + "dependencies": { + "acorn-walk": { + "version": "8.2.0", + "dev": true + } + } + }, + "keypair": { + "version": "1.0.4" + }, + "kind-of": { + "version": "6.0.3", + "dev": true + }, + "kuler": { + "version": "2.0.0" + }, + "labeled-stream-splicer": { + "version": "2.0.2", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "stream-splicer": "^2.0.0" + } + }, + "language-subtag-registry": { + "version": "0.3.22", + "dev": true + }, + "language-tags": { + "version": "1.0.5", + "dev": true, + "requires": { + "language-subtag-registry": "~0.3.2" + } + }, + "level": { + "version": "8.0.0", + "requires": { + "browser-level": "^1.0.1", + "classic-level": "^1.2.0" + } + }, + "level-codec": { + "version": "10.0.0", + "dev": true, + "requires": { + "buffer": "^6.0.3" + } + }, + "level-concat-iterator": { + "version": "3.1.0", + "dev": true, + "requires": { + "catering": "^2.1.0" + } + }, + "level-errors": { + "version": "3.0.1", + "dev": true + }, + "level-iterator-stream": { + "version": "5.0.0", + "dev": true, + "requires": { + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "level-js": { + "version": "6.1.0", + "dev": true, + "requires": { + "abstract-leveldown": "^7.2.0", + "buffer": "^6.0.3", + "inherits": "^2.0.3", + "ltgt": "^2.1.2", + "run-parallel-limit": "^1.1.0" + } + }, + "level-legacy": { + "version": "npm:level@7.0.1", + "dev": true, + "requires": { + "level-js": "^6.1.0", + "level-packager": "^6.0.1", + "leveldown": "^6.1.0" + } + }, + "level-mem": { + "version": "6.0.1", + "dev": true, + "requires": { + "level-packager": "^6.0.1", + "memdown": "^6.1.1" + } + }, + "level-packager": { + "version": "6.0.1", + "dev": true, + "requires": { + "encoding-down": "^7.1.0", + "levelup": "^5.1.1" + } + }, + "level-supports": { + "version": "4.0.1" + }, + "level-transcoder": { + "version": "1.0.1", + "requires": { + "buffer": "^6.0.3", + "module-error": "^1.0.1" + } + }, + "leveldown": { + "version": "6.1.1", + "dev": true, + "requires": { + "abstract-leveldown": "^7.2.0", + "napi-macros": "~2.0.0", + "node-gyp-build": "^4.3.0" + } + }, + "levelup": { + "version": "5.1.1", + "dev": true, + "requires": { + "catering": "^2.0.0", + "deferred-leveldown": "^7.0.0", + "level-errors": "^3.0.1", + "level-iterator-stream": "^5.0.0", + "level-supports": "^2.0.1", + "queue-microtask": "^1.2.3" + }, + "dependencies": { + "level-supports": { + "version": "2.1.0", + "dev": true + } + } + }, + "levn": { + "version": "0.4.1", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + } + }, + "libp2p": { + "version": "0.30.13", + "requires": { + "@motrix/nat-api": "^0.3.1", + "abort-controller": "^3.0.0", + "aggregate-error": "^3.1.0", + "any-signal": "^2.1.1", + "bignumber.js": "^9.0.1", + "cids": "^1.1.5", + "class-is": "^1.1.0", + "debug": "^4.3.1", + "err-code": "^2.0.0", + "es6-promisify": "^6.1.1", + "events": "^3.2.0", + "hashlru": "^2.3.0", + "interface-datastore": "^3.0.3", + "ipfs-utils": "^6.0.0", + "it-all": "^1.0.4", + "it-buffer": "^0.1.2", + "it-drain": "^1.0.3", + "it-filter": "^1.0.1", + "it-first": "^1.0.4", + "it-handshake": "^1.0.2", + "it-length-prefixed": "^3.1.0", + "it-map": "^1.0.4", + "it-merge": "1.0.0", + "it-pipe": "^1.1.0", + "it-protocol-buffers": "^0.2.0", + "it-take": "1.0.0", + "libp2p-crypto": "^0.19.0", + "libp2p-interfaces": "^0.8.1", + "libp2p-utils": "^0.2.2", + "mafmt": "^8.0.0", + "merge-options": "^3.0.4", + "moving-average": "^1.0.0", + "multiaddr": "^8.1.0", + "multicodec": "^2.1.0", + "multihashing-async": "^2.0.1", + "multistream-select": "^1.0.0", + "mutable-proxy": "^1.0.0", + "node-forge": "^0.10.0", + "p-any": "^3.0.0", + "p-fifo": "^1.0.0", + "p-retry": "^4.2.0", + "p-settle": "^4.0.1", + "peer-id": "^0.14.2", + "private-ip": "^2.0.0", + "protons": "^2.0.0", + "retimer": "^2.0.0", + "sanitize-filename": "^1.6.3", + "set-delayed-interval": "^1.0.0", + "streaming-iterables": "^5.0.2", + "timeout-abort-controller": "^1.1.1", + "uint8arrays": "^2.1.3", + "varint": "^6.0.0", + "xsalsa20": "^1.0.2" + }, + "dependencies": { + "bl": { + "version": "4.1.0", + "requires": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "buffer": { + "version": "5.7.1", + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "delay": { + "version": "4.4.1" + }, + "es6-promisify": { + "version": "6.1.1" + }, + "events": { + "version": "3.3.0" + }, + "it-handshake": { + "version": "1.0.2", + "requires": { + "it-pushable": "^1.4.0", + "it-reader": "^2.0.0", + "p-defer": "^3.0.0" + } + }, + "it-length-prefixed": { + "version": "3.1.0", + "requires": { + "@types/bl": "^2.1.0", + "bl": "^4.0.2", + "buffer": "^5.5.0", + "varint": "^5.0.0" + }, + "dependencies": { + "varint": { + "version": "5.0.2" + } + } + }, + "it-reader": { + "version": "2.1.0", + "requires": { + "bl": "^4.0.0" + } + }, + "libp2p-interfaces": { + "version": "0.8.4", + "requires": { + "@types/bl": "^2.1.0", + "abort-controller": "^3.0.0", + "abortable-iterator": "^3.0.0", + "chai": "^4.2.0", + "chai-checkmark": "^1.0.1", + "debug": "^4.3.1", + "delay": "^4.4.0", + "detect-node": "^2.0.4", + "dirty-chai": "^2.0.1", + "err-code": "^2.0.3", + "it-goodbye": "^2.0.2", + "it-length-prefixed": "^3.1.0", + "it-pair": "^1.0.0", + "it-pipe": "^1.1.0", + "it-pushable": "^1.4.0", + "libp2p-crypto": "^0.19.0", + "libp2p-tcp": "^0.15.0", + "multiaddr": "^8.1.2", + "multibase": "^3.1.1", + "multihashes": "^3.1.1", + "p-defer": "^3.0.0", + "p-limit": "^3.1.0", + "p-wait-for": "^3.2.0", + "peer-id": "^0.14.2", + "protons": "^2.0.0", + "sinon": "^9.2.4", + "streaming-iterables": "^5.0.4", + "uint8arrays": "^2.0.5" + } + }, + "multiaddr": { + "version": "8.1.2", + "requires": { + "cids": "^1.0.0", + "class-is": "^1.1.0", + "dns-over-http-resolver": "^1.0.0", + "err-code": "^2.0.3", + "is-ip": "^3.1.0", + "multibase": "^3.0.0", + "uint8arrays": "^1.1.0", + "varint": "^5.0.0" + }, + "dependencies": { + "uint8arrays": { + "version": "1.1.0", + "requires": { + "multibase": "^3.0.0", + "web-encoding": "^1.0.2" + } + }, + "varint": { + "version": "5.0.2" + } + } + }, + "multibase": { + "version": "3.1.2", + "requires": { + "@multiformats/base-x": "^4.0.1", + "web-encoding": "^1.0.6" + } + }, + "multihashes": { + "version": "3.1.2", + "requires": { + "multibase": "^3.1.0", + "uint8arrays": "^2.0.5", + "varint": "^6.0.0" + } + }, + "readable-stream": { + "version": "3.6.0", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "uint8arrays": { + "version": "2.1.10", + "requires": { + "multiformats": "^9.4.2" + } + } + } + }, + "libp2p-bootstrap": { + "version": "0.14.0", + "requires": { + "debug": "^4.3.1", + "mafmt": "^10.0.0", + "multiaddr": "^10.0.0", + "peer-id": "^0.16.0" + }, + "dependencies": { + "err-code": { + "version": "3.0.1" + }, + "libp2p-crypto": { + "version": "0.21.2", + "requires": { + "@noble/ed25519": "^1.5.1", + "@noble/secp256k1": "^1.3.0", + "err-code": "^3.0.1", + "iso-random-stream": "^2.0.0", + "multiformats": "^9.4.5", + "node-forge": "^1.2.1", + "protobufjs": "^6.11.2", + "uint8arrays": "^3.0.0" + } + }, + "mafmt": { + "version": "10.0.0", + "requires": { + "multiaddr": "^10.0.0" + } + }, + "node-forge": { + "version": "1.3.1" + }, + "peer-id": { + "version": "0.16.0", + "requires": { + "class-is": "^1.1.0", + "libp2p-crypto": "^0.21.0", + "multiformats": "^9.4.5", + "protobufjs": "^6.10.2", + "uint8arrays": "^3.0.0" + } + } + } + }, + "libp2p-crypto": { + "version": "0.19.7", + "requires": { + "err-code": "^3.0.1", + "is-typedarray": "^1.0.0", + "iso-random-stream": "^2.0.0", + "keypair": "^1.0.1", + "multiformats": "^9.4.5", + "node-forge": "^0.10.0", + "pem-jwk": "^2.0.0", + "protobufjs": "^6.11.2", + "secp256k1": "^4.0.0", + "uint8arrays": "^3.0.0", + "ursa-optional": "^0.10.1" + }, + "dependencies": { + "err-code": { + "version": "3.0.1" + } + } + }, + "libp2p-interfaces": { + "version": "1.3.1", + "requires": { + "abort-controller": "^3.0.0", + "abortable-iterator": "^3.0.0", + "debug": "^4.3.1", + "err-code": "^3.0.1", + "it-length-prefixed": "^5.0.2", + "it-pipe": "^1.1.0", + "it-pushable": "^1.4.2", + "libp2p-crypto": "^0.20.0", + "multiaddr": "^10.0.0", + "multiformats": "^9.1.2", + "p-queue": "^6.6.2", + "peer-id": "^0.15.4", + "protobufjs": "^6.10.2", + "uint8arrays": "^3.0.0" + }, + "dependencies": { + "err-code": { + "version": "3.0.1" + }, + "libp2p-crypto": { + "version": "0.20.0", + "requires": { + "err-code": "^3.0.1", + "iso-random-stream": "^2.0.0", + "keypair": "^1.0.4", + "multiformats": "^9.4.5", + "noble-ed25519": "^1.2.6", + "noble-secp256k1": "^1.2.10", + "node-forge": "^0.10.0", + "pem-jwk": "^2.0.0", + "protobufjs": "^6.11.2", + "uint8arrays": "^3.0.0", + "ursa-optional": "^0.10.1" + } + }, + "peer-id": { + "version": "0.15.4", + "requires": { + "class-is": "^1.1.0", + "libp2p-crypto": "^0.20.0", + "minimist": "^1.2.5", + "multiformats": "^9.4.5", + "protobufjs": "^6.10.2", + "uint8arrays": "^3.0.0" + } + } + } + }, + "libp2p-kad-dht": { + "version": "0.20.6", + "requires": { + "abort-controller": "^3.0.0", + "async": "^2.6.2", + "base32.js": "~0.1.0", + "cids": "^1.1.5", + "debug": "^4.3.1", + "err-code": "^2.0.3", + "hashlru": "^2.3.0", + "heap": "~0.2.6", + "interface-datastore": "^3.0.3", + "it-length-prefixed": "^3.1.0", + "it-pipe": "^1.1.0", + "k-bucket": "^5.0.0", + "libp2p-crypto": "^0.19.0", + "libp2p-interfaces": "^0.8.2", + "libp2p-record": "^0.9.0", + "multiaddr": "^8.1.2", + "multihashing-async": "^2.0.1", + "p-filter": "^2.1.0", + "p-map": "^4.0.0", + "p-queue": "^6.6.2", + "p-timeout": "^4.1.0", + "p-times": "^3.0.0", + "peer-id": "^0.14.2", + "promise-to-callback": "^1.0.0", + "protons": "^2.0.0", + "streaming-iterables": "^5.0.4", + "uint8arrays": "^2.0.5", + "varint": "^5.0.0", + "xor-distance": "^2.0.0" + }, + "dependencies": { + "async": { + "version": "2.6.4", + "requires": { + "lodash": "^4.17.14" + } + }, + "bl": { + "version": "4.1.0", + "requires": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "buffer": { + "version": "5.7.1", + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "delay": { + "version": "4.4.1" + }, + "it-length-prefixed": { + "version": "3.1.0", + "requires": { + "@types/bl": "^2.1.0", + "bl": "^4.0.2", + "buffer": "^5.5.0", + "varint": "^5.0.0" + } + }, + "libp2p-interfaces": { + "version": "0.8.4", + "requires": { + "@types/bl": "^2.1.0", + "abort-controller": "^3.0.0", + "abortable-iterator": "^3.0.0", + "chai": "^4.2.0", + "chai-checkmark": "^1.0.1", + "debug": "^4.3.1", + "delay": "^4.4.0", + "detect-node": "^2.0.4", + "dirty-chai": "^2.0.1", + "err-code": "^2.0.3", + "it-goodbye": "^2.0.2", + "it-length-prefixed": "^3.1.0", + "it-pair": "^1.0.0", + "it-pipe": "^1.1.0", + "it-pushable": "^1.4.0", + "libp2p-crypto": "^0.19.0", + "libp2p-tcp": "^0.15.0", + "multiaddr": "^8.1.2", + "multibase": "^3.1.1", + "multihashes": "^3.1.1", + "p-defer": "^3.0.0", + "p-limit": "^3.1.0", + "p-wait-for": "^3.2.0", + "peer-id": "^0.14.2", + "protons": "^2.0.0", + "sinon": "^9.2.4", + "streaming-iterables": "^5.0.4", + "uint8arrays": "^2.0.5" + } + }, + "multiaddr": { + "version": "8.1.2", + "requires": { + "cids": "^1.0.0", + "class-is": "^1.1.0", + "dns-over-http-resolver": "^1.0.0", + "err-code": "^2.0.3", + "is-ip": "^3.1.0", + "multibase": "^3.0.0", + "uint8arrays": "^1.1.0", + "varint": "^5.0.0" + }, + "dependencies": { + "uint8arrays": { + "version": "1.1.0", + "requires": { + "multibase": "^3.0.0", + "web-encoding": "^1.0.2" + } + } + } + }, + "multibase": { + "version": "3.1.2", + "requires": { + "@multiformats/base-x": "^4.0.1", + "web-encoding": "^1.0.6" + } + }, + "multihashes": { + "version": "3.1.2", + "requires": { + "multibase": "^3.1.0", + "uint8arrays": "^2.0.5", + "varint": "^6.0.0" + }, + "dependencies": { + "varint": { + "version": "6.0.0" + } + } + }, + "readable-stream": { + "version": "3.6.0", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "uint8arrays": { + "version": "2.1.10", + "requires": { + "multiformats": "^9.4.2" + } + }, + "varint": { + "version": "5.0.2" + } + } + }, + "libp2p-mplex": { + "version": "0.10.7", + "requires": { + "abortable-iterator": "^3.0.2", + "bl": "^5.0.0", + "debug": "^4.3.1", + "err-code": "^3.0.1", + "it-pipe": "^1.1.0", + "it-pushable": "^1.4.1", + "varint": "^6.0.0" + }, + "dependencies": { + "bl": { + "version": "5.1.0", + "requires": { + "buffer": "^6.0.3", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "err-code": { + "version": "3.0.1" + }, + "readable-stream": { + "version": "3.6.0", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "libp2p-record": { + "version": "0.9.0", + "requires": { + "err-code": "^2.0.0", + "multihashes": "^3.0.1", + "multihashing-async": "^2.0.1", + "protons": "^2.0.0", + "uint8arrays": "^1.1.0" + }, + "dependencies": { + "multibase": { + "version": "3.1.2", + "requires": { + "@multiformats/base-x": "^4.0.1", + "web-encoding": "^1.0.6" + } + }, + "multihashes": { + "version": "3.1.2", + "requires": { + "multibase": "^3.1.0", + "uint8arrays": "^2.0.5", + "varint": "^6.0.0" + }, + "dependencies": { + "uint8arrays": { + "version": "2.1.10", + "requires": { + "multiformats": "^9.4.2" + } + } + } + }, + "uint8arrays": { + "version": "1.1.0", + "requires": { + "multibase": "^3.0.0", + "web-encoding": "^1.0.2" + } + } + } + }, + "libp2p-tcp": { + "version": "0.15.4", + "requires": { + "abortable-iterator": "^3.0.0", + "class-is": "^1.1.0", + "debug": "^4.3.1", + "err-code": "^3.0.1", + "libp2p-utils": "^0.3.0", + "mafmt": "^9.0.0", + "multiaddr": "^9.0.1", + "stream-to-it": "^0.2.2" + }, + "dependencies": { + "err-code": { + "version": "3.0.1" + }, + "ip-address": { + "version": "7.1.0", + "requires": { + "jsbn": "1.1.0", + "sprintf-js": "1.1.2" + } + }, + "libp2p-utils": { + "version": "0.3.1", + "requires": { + "abortable-iterator": "^3.0.0", + "debug": "^4.3.0", + "err-code": "^3.0.1", + "ip-address": "^7.1.0", + "is-loopback-addr": "^1.0.0", + "multiaddr": "^9.0.1", + "private-ip": "^2.1.1" + } + }, + "mafmt": { + "version": "9.0.0", + "requires": { + "multiaddr": "^9.0.1" + } + }, + "multiaddr": { + "version": "9.0.2", + "requires": { + "cids": "^1.0.0", + "dns-over-http-resolver": "^1.0.0", + "err-code": "^3.0.1", + "is-ip": "^3.1.0", + "multibase": "^4.0.2", + "uint8arrays": "^2.1.3", + "varint": "^6.0.0" + } + }, + "uint8arrays": { + "version": "2.1.10", + "requires": { + "multiformats": "^9.4.2" + } + } + } + }, + "libp2p-utils": { + "version": "0.2.3", + "requires": { + "abortable-iterator": "^3.0.0", + "debug": "^4.2.0", + "err-code": "^2.0.3", + "ip-address": "^6.1.0", + "is-loopback-addr": "^1.0.0", + "multiaddr": "^8.0.0", + "private-ip": "^2.1.1" + }, + "dependencies": { + "multiaddr": { + "version": "8.1.2", + "requires": { + "cids": "^1.0.0", + "class-is": "^1.1.0", + "dns-over-http-resolver": "^1.0.0", + "err-code": "^2.0.3", + "is-ip": "^3.1.0", + "multibase": "^3.0.0", + "uint8arrays": "^1.1.0", + "varint": "^5.0.0" + } + }, + "multibase": { + "version": "3.1.2", + "requires": { + "@multiformats/base-x": "^4.0.1", + "web-encoding": "^1.0.6" + } + }, + "uint8arrays": { + "version": "1.1.0", + "requires": { + "multibase": "^3.0.0", + "web-encoding": "^1.0.2" + } + }, + "varint": { + "version": "5.0.2" + } + } + }, + "libp2p-websockets": { + "version": "0.15.9", + "requires": { + "abortable-iterator": "^3.0.0", + "class-is": "^1.1.0", + "debug": "^4.3.1", + "err-code": "^3.0.1", + "ipfs-utils": "^8.1.2", + "it-ws": "^4.0.0", + "libp2p-utils": "^0.3.0", + "mafmt": "^9.0.0", + "multiaddr": "^9.0.1", + "multiaddr-to-uri": "^7.0.0", + "p-defer": "^3.0.0", + "p-timeout": "^4.1.0" + }, + "dependencies": { + "err-code": { + "version": "3.0.1" + }, + "ip-address": { + "version": "7.1.0", + "requires": { + "jsbn": "1.1.0", + "sprintf-js": "1.1.2" + } + }, + "ipfs-utils": { + "version": "8.1.6", + "requires": { + "abort-controller": "^3.0.0", + "any-signal": "^2.1.0", + "buffer": "^6.0.1", + "electron-fetch": "^1.7.2", + "err-code": "^3.0.1", + "is-electron": "^2.2.0", + "iso-url": "^1.1.5", + "it-glob": "~0.0.11", + "it-to-stream": "^1.0.0", + "merge-options": "^3.0.4", + "nanoid": "^3.1.20", + "native-abort-controller": "^1.0.3", + "native-fetch": "^3.0.0", + "node-fetch": "https://registry.npmjs.org/@achingbrain/node-fetch/-/node-fetch-2.6.7.tgz", + "react-native-fetch-api": "^2.0.0", + "stream-to-it": "^0.2.2" + } + }, + "libp2p-utils": { + "version": "0.3.1", + "requires": { + "abortable-iterator": "^3.0.0", + "debug": "^4.3.0", + "err-code": "^3.0.1", + "ip-address": "^7.1.0", + "is-loopback-addr": "^1.0.0", + "multiaddr": "^9.0.1", + "private-ip": "^2.1.1" + } + }, + "mafmt": { + "version": "9.0.0", + "requires": { + "multiaddr": "^9.0.1" + } + }, + "multiaddr": { + "version": "9.0.2", + "requires": { + "cids": "^1.0.0", + "dns-over-http-resolver": "^1.0.0", + "err-code": "^3.0.1", + "is-ip": "^3.1.0", + "multibase": "^4.0.2", + "uint8arrays": "^2.1.3", + "varint": "^6.0.0" + } + }, + "node-fetch": { + "version": "npm:@achingbrain/node-fetch@2.6.7" + }, + "uint8arrays": { + "version": "2.1.10", + "requires": { + "multiformats": "^9.4.2" + } + } + } + }, + "lilconfig": { + "version": "2.0.5", + "dev": true + }, + "lint-staged": { + "version": "13.0.3", + "dev": true, + "requires": { + "cli-truncate": "^3.1.0", + "colorette": "^2.0.17", + "commander": "^9.3.0", + "debug": "^4.3.4", + "execa": "^6.1.0", + "lilconfig": "2.0.5", + "listr2": "^4.0.5", + "micromatch": "^4.0.5", + "normalize-path": "^3.0.0", + "object-inspect": "^1.12.2", + "pidtree": "^0.6.0", + "string-argv": "^0.3.1", + "yaml": "^2.1.1" + }, + "dependencies": { + "commander": { + "version": "9.4.1", + "dev": true + }, + "execa": { + "version": "6.1.0", + "dev": true, + "requires": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.1", + "human-signals": "^3.0.1", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^3.0.7", + "strip-final-newline": "^3.0.0" + } + }, + "human-signals": { + "version": "3.0.1", + "dev": true + }, + "is-stream": { + "version": "3.0.0", + "dev": true + }, + "mimic-fn": { + "version": "4.0.0", + "dev": true + }, + "npm-run-path": { + "version": "5.1.0", + "dev": true, + "requires": { + "path-key": "^4.0.0" + } + }, + "onetime": { + "version": "6.0.0", + "dev": true, + "requires": { + "mimic-fn": "^4.0.0" + } + }, + "path-key": { + "version": "4.0.0", + "dev": true + }, + "strip-final-newline": { + "version": "3.0.0", + "dev": true + } + } + }, + "listr2": { + "version": "4.0.5", + "dev": true, + "requires": { + "cli-truncate": "^2.1.0", + "colorette": "^2.0.16", + "log-update": "^4.0.0", + "p-map": "^4.0.0", + "rfdc": "^1.3.0", + "rxjs": "^7.5.5", + "through": "^2.3.8", + "wrap-ansi": "^7.0.0" + }, + "dependencies": { + "cli-truncate": { + "version": "2.1.0", + "dev": true, + "requires": { + "slice-ansi": "^3.0.0", + "string-width": "^4.2.0" + } + }, + "emoji-regex": { + "version": "8.0.0", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "dev": true + }, + "slice-ansi": { + "version": "3.0.0", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + } + }, + "string-width": { + "version": "4.2.3", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + } + } + }, + "lmdb": { + "version": "2.6.8", + "dev": true, + "requires": { + "@lmdb/lmdb-darwin-arm64": "2.6.8", + "@lmdb/lmdb-darwin-x64": "2.6.8", + "@lmdb/lmdb-linux-arm": "2.6.8", + "@lmdb/lmdb-linux-arm64": "2.6.8", + "@lmdb/lmdb-linux-x64": "2.6.8", + "@lmdb/lmdb-win32-x64": "2.6.8", + "msgpackr": "1.7.2", + "node-addon-api": "^4.3.0", + "node-gyp-build-optional-packages": "5.0.3", + "ordered-binary": "^1.4.0", + "weak-lru-cache": "^1.2.2" + } + }, + "load-json-file": { + "version": "4.0.0", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + }, + "dependencies": { + "strip-bom": { + "version": "3.0.0", + "dev": true + } + } + }, + "loader-runner": { + "version": "4.3.0", + "dev": true + }, + "loader-utils": { + "version": "2.0.3", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + } + }, + "locate-path": { + "version": "6.0.0", + "dev": true, + "requires": { + "p-locate": "^5.0.0" + } + }, + "lodash": { + "version": "4.17.21" + }, + "lodash.camelcase": { + "version": "4.3.0", + "dev": true + }, + "lodash.cond": { + "version": "4.5.2", + "dev": true + }, + "lodash.debounce": { + "version": "4.0.8", + "dev": true + }, + "lodash.find": { + "version": "4.6.0" + }, + "lodash.flattendeep": { + "version": "4.4.0", + "dev": true + }, + "lodash.get": { + "version": "4.4.2" + }, + "lodash.kebabcase": { + "version": "4.1.1", + "dev": true + }, + "lodash.max": { + "version": "4.0.1" + }, + "lodash.memoize": { + "version": "3.0.4", + "dev": true + }, + "lodash.merge": { + "version": "4.6.2" + }, + "lodash.padstart": { + "version": "4.6.1" + }, + "lodash.repeat": { + "version": "4.1.0" + }, + "lodash.snakecase": { + "version": "4.1.1", + "dev": true + }, + "lodash.upperfirst": { + "version": "4.3.1", + "dev": true + }, + "log-update": { + "version": "4.0.0", + "dev": true, + "requires": { + "ansi-escapes": "^4.3.0", + "cli-cursor": "^3.1.0", + "slice-ansi": "^4.0.0", + "wrap-ansi": "^6.2.0" + }, + "dependencies": { + "emoji-regex": { + "version": "8.0.0", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "dev": true + }, + "slice-ansi": { + "version": "4.0.0", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + } + }, + "string-width": { + "version": "4.2.3", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "wrap-ansi": { + "version": "6.2.0", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + } + } + }, + "log4js": { + "version": "6.7.0", + "dev": true, + "requires": { + "date-format": "^4.0.14", + "debug": "^4.3.4", + "flatted": "^3.2.7", + "rfdc": "^1.3.0", + "streamroller": "^3.1.3" + } + }, + "logform": { + "version": "2.4.2", + "requires": { + "@colors/colors": "1.5.0", + "fecha": "^4.2.0", + "ms": "^2.1.1", + "safe-stable-stringify": "^2.3.1", + "triple-beam": "^1.3.0" + }, + "dependencies": { + "ms": { + "version": "2.1.3" + } + } + }, + "lolex": { + "version": "1.6.0", + "dev": true + }, + "long": { + "version": "4.0.0" + }, + "loupe": { + "version": "2.3.4", + "requires": { + "get-func-name": "^2.0.0" + } + }, + "lower-case": { + "version": "1.1.4", + "dev": true + }, + "lru-cache": { + "version": "7.18.3" + }, + "ltgt": { + "version": "2.2.1", + "dev": true + }, + "lunr": { + "version": "2.3.9", + "dev": true + }, + "mafmt": { + "version": "8.0.4", + "requires": { + "multiaddr": "^8.0.0" + }, + "dependencies": { + "multiaddr": { + "version": "8.1.2", + "requires": { + "cids": "^1.0.0", + "class-is": "^1.1.0", + "dns-over-http-resolver": "^1.0.0", + "err-code": "^2.0.3", + "is-ip": "^3.1.0", + "multibase": "^3.0.0", + "uint8arrays": "^1.1.0", + "varint": "^5.0.0" + } + }, + "multibase": { + "version": "3.1.2", + "requires": { + "@multiformats/base-x": "^4.0.1", + "web-encoding": "^1.0.6" + } + }, + "uint8arrays": { + "version": "1.1.0", + "requires": { + "multibase": "^3.0.0", + "web-encoding": "^1.0.2" + } + }, + "varint": { + "version": "5.0.2" + } + } + }, + "magic-string": { + "version": "0.25.9", + "dev": true, + "requires": { + "sourcemap-codec": "^1.4.8" + } + }, + "make-dir": { + "version": "1.3.0", + "dev": true, + "requires": { + "pify": "^3.0.0" + } + }, + "make-error": { + "version": "1.3.6", + "dev": true + }, + "marked": { + "version": "4.1.1", + "dev": true + }, + "mcl-wasm": { + "version": "0.7.9" + }, + "md5.js": { + "version": "1.3.5", + "dev": true, + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "media-typer": { + "version": "0.3.0" + }, + "memdown": { + "version": "6.1.1", + "dev": true, + "requires": { + "abstract-leveldown": "^7.2.0", + "buffer": "^6.0.3", + "functional-red-black-tree": "^1.0.1", + "inherits": "^2.0.1", + "ltgt": "^2.2.0" + } + }, + "memory-level": { + "version": "1.0.0", + "requires": { + "abstract-level": "^1.0.0", + "functional-red-black-tree": "^1.0.1", + "module-error": "^1.0.1" + } + }, + "memorystream": { + "version": "0.3.1", + "dev": true + }, + "merge-options": { + "version": "3.0.4", + "requires": { + "is-plain-obj": "^2.1.0" + } + }, + "merge-source-map": { + "version": "1.0.4", + "dev": true, + "requires": { + "source-map": "^0.5.6" + } + }, + "merge-stream": { + "version": "2.0.0" + }, + "merge2": { + "version": "1.4.1", + "dev": true + }, + "methods": { + "version": "1.1.2", + "dev": true + }, + "micro-bmark": { + "version": "0.2.0", + "dev": true + }, + "micromatch": { + "version": "4.0.5", + "dev": true, + "requires": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + } + }, + "miller-rabin": { + "version": "4.0.1", + "dev": true, + "requires": { + "bn.js": "^4.0.0", + "brorand": "^1.0.1" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "dev": true + } + } + }, + "mime": { + "version": "2.6.0", + "dev": true + }, + "mime-db": { + "version": "1.52.0" + }, + "mime-types": { + "version": "2.1.35", + "requires": { + "mime-db": "1.52.0" + } + }, + "mimic-fn": { + "version": "2.1.0" + }, + "minimalistic-assert": { + "version": "1.0.1" + }, + "minimalistic-crypto-utils": { + "version": "1.0.1" + }, + "minimatch": { + "version": "3.1.2", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.7" + }, + "mkdirp": { + "version": "0.5.6", + "dev": true, + "requires": { + "minimist": "^1.2.6" + } + }, + "mkdirp-classic": { + "version": "0.5.3", + "dev": true + }, + "module-deps": { + "version": "6.2.3", + "dev": true, + "requires": { + "browser-resolve": "^2.0.0", + "cached-path-relative": "^1.0.2", + "concat-stream": "~1.6.0", + "defined": "^1.0.0", + "detective": "^5.2.0", + "duplexer2": "^0.1.2", + "inherits": "^2.0.1", + "JSONStream": "^1.0.3", + "parents": "^1.0.0", + "readable-stream": "^2.0.2", + "resolve": "^1.4.0", + "stream-combiner2": "^1.1.1", + "subarg": "^1.0.0", + "through2": "^2.0.0", + "xtend": "^4.0.0" + } + }, + "module-error": { + "version": "1.0.2" + }, + "moment": { + "version": "2.29.4" + }, + "morphdom": { + "version": "2.6.1", + "dev": true + }, + "moving-average": { + "version": "1.0.1" + }, + "ms": { + "version": "0.7.3" + }, + "msgpackr": { + "version": "1.7.2", + "dev": true, + "requires": { + "msgpackr-extract": "^2.1.2" + } + }, + "msgpackr-extract": { + "version": "2.1.2", + "dev": true, + "optional": true, + "requires": { + "@msgpackr-extract/msgpackr-extract-darwin-arm64": "2.1.2", + "@msgpackr-extract/msgpackr-extract-darwin-x64": "2.1.2", + "@msgpackr-extract/msgpackr-extract-linux-arm": "2.1.2", + "@msgpackr-extract/msgpackr-extract-linux-arm64": "2.1.2", + "@msgpackr-extract/msgpackr-extract-linux-x64": "2.1.2", + "@msgpackr-extract/msgpackr-extract-win32-x64": "2.1.2", + "node-gyp-build-optional-packages": "5.0.3" + } + }, + "multiaddr": { + "version": "10.0.1", + "requires": { + "dns-over-http-resolver": "^1.2.3", + "err-code": "^3.0.1", + "is-ip": "^3.1.0", + "multiformats": "^9.4.5", + "uint8arrays": "^3.0.0", + "varint": "^6.0.0" + }, + "dependencies": { + "err-code": { + "version": "3.0.1" + } + } + }, + "multiaddr-to-uri": { + "version": "7.0.0", + "requires": { + "multiaddr": "^9.0.1" + }, + "dependencies": { + "err-code": { + "version": "3.0.1" + }, + "multiaddr": { + "version": "9.0.2", + "requires": { + "cids": "^1.0.0", + "dns-over-http-resolver": "^1.0.0", + "err-code": "^3.0.1", + "is-ip": "^3.1.0", + "multibase": "^4.0.2", + "uint8arrays": "^2.1.3", + "varint": "^6.0.0" + } + }, + "uint8arrays": { + "version": "2.1.10", + "requires": { + "multiformats": "^9.4.2" + } + } + } + }, + "multibase": { + "version": "4.0.6", + "requires": { + "@multiformats/base-x": "^4.0.1" + } + }, + "multicodec": { + "version": "2.1.3", + "requires": { + "uint8arrays": "1.1.0", + "varint": "^6.0.0" + }, + "dependencies": { + "multibase": { + "version": "3.1.2", + "requires": { + "@multiformats/base-x": "^4.0.1", + "web-encoding": "^1.0.6" + } + }, + "uint8arrays": { + "version": "1.1.0", + "requires": { + "multibase": "^3.0.0", + "web-encoding": "^1.0.2" + } + } + } + }, + "multiformats": { + "version": "9.9.0" + }, + "multihashes": { + "version": "4.0.3", + "requires": { + "multibase": "^4.0.1", + "uint8arrays": "^3.0.0", + "varint": "^5.0.2" + }, + "dependencies": { + "varint": { + "version": "5.0.2" + } + } + }, + "multihashing-async": { + "version": "2.1.4", + "requires": { + "blakejs": "^1.1.0", + "err-code": "^3.0.0", + "js-sha3": "^0.8.0", + "multihashes": "^4.0.1", + "murmurhash3js-revisited": "^3.0.0", + "uint8arrays": "^3.0.0" + }, + "dependencies": { + "err-code": { + "version": "3.0.1" + } + } + }, + "multistream-select": { + "version": "1.0.0", + "requires": { + "bl": "^4.0.0", + "debug": "^4.1.1", + "err-code": "^2.0.0", + "it-handshake": "^1.0.2", + "it-length-prefixed": "^3.0.0", + "it-pipe": "^1.0.1", + "it-reader": "^2.0.0", + "p-defer": "^3.0.0", + "uint8arrays": "^1.1.0" + }, + "dependencies": { + "bl": { + "version": "4.1.0", + "requires": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "buffer": { + "version": "5.7.1", + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "it-handshake": { + "version": "1.0.2", + "requires": { + "it-pushable": "^1.4.0", + "it-reader": "^2.0.0", + "p-defer": "^3.0.0" + } + }, + "it-length-prefixed": { + "version": "3.1.0", + "requires": { + "@types/bl": "^2.1.0", + "bl": "^4.0.2", + "buffer": "^5.5.0", + "varint": "^5.0.0" + } + }, + "it-reader": { + "version": "2.1.0", + "requires": { + "bl": "^4.0.0" + } + }, + "multibase": { + "version": "3.1.2", + "requires": { + "@multiformats/base-x": "^4.0.1", + "web-encoding": "^1.0.6" + } + }, + "readable-stream": { + "version": "3.6.0", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "uint8arrays": { + "version": "1.1.0", + "requires": { + "multibase": "^3.0.0", + "web-encoding": "^1.0.2" + } + }, + "varint": { + "version": "5.0.2" + } + } + }, + "murmurhash3js-revisited": { + "version": "3.0.0" + }, + "mutable-proxy": { + "version": "1.0.0" + }, + "mute-stream": { + "version": "0.0.5", + "dev": true + }, + "mutexify": { + "version": "1.4.0", + "dev": true, + "requires": { + "queue-tick": "^1.0.0" + } + }, + "nan": { + "version": "2.17.0" + }, + "nanoassert": { + "version": "1.1.0", + "dev": true + }, + "nanobench": { + "version": "2.1.1", + "dev": true, + "requires": { + "browser-process-hrtime": "^0.1.2", + "chalk": "^1.1.3", + "mutexify": "^1.1.0", + "pretty-hrtime": "^1.0.2" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "dev": true + } + } + }, + "nanohtml": { + "version": "1.10.0", + "dev": true, + "requires": { + "acorn-node": "^1.8.2", + "camel-case": "^3.0.0", + "convert-source-map": "^1.5.1", + "estree-is-member-expression": "^1.0.0", + "hyperx": "^2.5.0", + "is-boolean-attribute": "0.0.1", + "nanoassert": "^1.1.0", + "nanobench": "^2.1.0", + "normalize-html-whitespace": "^0.2.0", + "through2": "^2.0.3", + "transform-ast": "^2.4.0" + }, + "dependencies": { + "convert-source-map": { + "version": "1.9.0", + "dev": true + } + } + }, + "nanoid": { + "version": "3.3.4" + }, + "napi-macros": { + "version": "2.0.0" + }, + "native-abort-controller": { + "version": "1.0.4", + "requires": {} + }, + "native-fetch": { + "version": "3.0.0", + "requires": {} + }, + "natural-compare": { + "version": "1.4.0", + "dev": true + }, + "negotiator": { + "version": "0.6.3", + "dev": true + }, + "neo-async": { + "version": "2.6.2", + "dev": true + }, + "netmask": { + "version": "2.0.2" + }, + "next-tick": { + "version": "1.1.0", + "dev": true + }, + "nise": { + "version": "4.1.0", + "requires": { + "@sinonjs/commons": "^1.7.0", + "@sinonjs/fake-timers": "^6.0.0", + "@sinonjs/text-encoding": "^0.7.1", + "just-extend": "^4.0.2", + "path-to-regexp": "^1.7.0" + } + }, + "no-case": { + "version": "2.3.2", + "dev": true, + "requires": { + "lower-case": "^1.1.1" + } + }, + "noble-ed25519": { + "version": "1.2.6" + }, + "noble-secp256k1": { + "version": "1.2.14" + }, + "node-addon-api": { + "version": "4.3.0", + "dev": true + }, + "node-dir": { + "version": "0.1.17", + "dev": true, + "requires": { + "minimatch": "^3.0.2" + } + }, + "node-fetch": { + "version": "2.6.7", + "requires": { + "whatwg-url": "^5.0.0" + } + }, + "node-forge": { + "version": "0.10.0" + }, + "node-gyp-build": { + "version": "4.5.0" + }, + "node-gyp-build-optional-packages": { + "version": "5.0.3", + "dev": true + }, + "node-preload": { + "version": "0.2.1", + "dev": true, + "requires": { + "process-on-spawn": "^1.0.0" + } + }, + "node-releases": { + "version": "2.0.6", + "dev": true + }, + "normalize-html-whitespace": { + "version": "0.2.0", + "dev": true + }, + "normalize-path": { + "version": "3.0.0", + "dev": true + }, + "npm-run-path": { + "version": "4.0.1", + "requires": { + "path-key": "^3.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "dev": true + }, + "nyc": { + "version": "15.1.0", + "dev": true, + "requires": { + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "caching-transform": "^4.0.0", + "convert-source-map": "^1.7.0", + "decamelize": "^1.2.0", + "find-cache-dir": "^3.2.0", + "find-up": "^4.1.0", + "foreground-child": "^2.0.0", + "get-package-type": "^0.1.0", + "glob": "^7.1.6", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-hook": "^3.0.0", + "istanbul-lib-instrument": "^4.0.0", + "istanbul-lib-processinfo": "^2.0.2", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.0.2", + "make-dir": "^3.0.0", + "node-preload": "^0.2.1", + "p-map": "^3.0.0", + "process-on-spawn": "^1.0.0", + "resolve-from": "^5.0.0", + "rimraf": "^3.0.0", + "signal-exit": "^3.0.2", + "spawn-wrap": "^2.0.0", + "test-exclude": "^6.0.0", + "yargs": "^15.0.2" + }, + "dependencies": { + "cliui": { + "version": "6.0.0", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "convert-source-map": { + "version": "1.9.0", + "dev": true + }, + "emoji-regex": { + "version": "8.0.0", + "dev": true + }, + "find-up": { + "version": "4.1.0", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "dev": true + }, + "locate-path": { + "version": "5.0.0", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "make-dir": { + "version": "3.1.0", + "dev": true, + "requires": { + "semver": "^6.0.0" + } + }, + "p-limit": { + "version": "2.3.0", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "p-map": { + "version": "3.0.0", + "dev": true, + "requires": { + "aggregate-error": "^3.0.0" + } + }, + "resolve-from": { + "version": "5.0.0", + "dev": true + }, + "semver": { + "version": "6.3.0", + "dev": true + }, + "string-width": { + "version": "4.2.3", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "wrap-ansi": { + "version": "6.2.0", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "y18n": { + "version": "4.0.3", + "dev": true + }, + "yargs": { + "version": "15.4.1", + "dev": true, + "requires": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + } + }, + "yargs-parser": { + "version": "18.1.3", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } + }, + "oauth-sign": { + "version": "0.9.0" + }, + "object-assign": { + "version": "4.1.1" + }, + "object-hash": { + "version": "2.2.0" + }, + "object-inspect": { + "version": "1.12.2" + }, + "object-is": { + "version": "1.1.5", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + } + }, + "object-keys": { + "version": "1.1.1" + }, + "object.assign": { + "version": "4.1.4", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + } + }, + "object.values": { + "version": "1.1.5", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1" + } + }, + "on-finished": { + "version": "2.4.1", + "requires": { + "ee-first": "1.1.1" + } + }, + "on-net-listen": { + "version": "1.1.2", + "dev": true + }, + "once": { + "version": "1.4.0", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "one-time": { + "version": "1.0.0", + "requires": { + "fn.name": "1.x.x" + } + }, + "onetime": { + "version": "5.1.2", + "requires": { + "mimic-fn": "^2.1.0" + } + }, + "opn": { + "version": "5.5.0", + "dev": true, + "requires": { + "is-wsl": "^1.1.0" + }, + "dependencies": { + "is-wsl": { + "version": "1.1.0", + "dev": true + } + } + }, + "optionator": { + "version": "0.9.1", + "dev": true, + "requires": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" + } + }, + "ordered-binary": { + "version": "1.4.0", + "dev": true + }, + "os-browserify": { + "version": "0.3.0", + "dev": true + }, + "os-homedir": { + "version": "1.0.2", + "dev": true + }, + "os-tmpdir": { + "version": "1.0.2", + "dev": true + }, + "p-any": { + "version": "3.0.0", + "requires": { + "p-cancelable": "^2.0.0", + "p-some": "^5.0.0" + } + }, + "p-cancelable": { + "version": "2.1.1" + }, + "p-defer": { + "version": "3.0.0" + }, + "p-fifo": { + "version": "1.0.0", + "requires": { + "fast-fifo": "^1.0.0", + "p-defer": "^3.0.0" + } + }, + "p-filter": { + "version": "2.1.0", + "requires": { + "p-map": "^2.0.0" + }, + "dependencies": { + "p-map": { + "version": "2.1.0" + } + } + }, + "p-finally": { + "version": "1.0.0" + }, + "p-limit": { + "version": "3.1.0", + "requires": { + "yocto-queue": "^0.1.0" + } + }, + "p-locate": { + "version": "5.0.0", + "dev": true, + "requires": { + "p-limit": "^3.0.2" + } + }, + "p-map": { + "version": "4.0.0", + "requires": { + "aggregate-error": "^3.0.0" + } + }, + "p-queue": { + "version": "6.6.2", + "requires": { + "eventemitter3": "^4.0.4", + "p-timeout": "^3.2.0" + }, + "dependencies": { + "p-timeout": { + "version": "3.2.0", + "requires": { + "p-finally": "^1.0.0" + } + } + } + }, + "p-reflect": { + "version": "2.1.0" + }, + "p-retry": { + "version": "4.6.2", + "requires": { + "@types/retry": "0.12.0", + "retry": "^0.13.1" + } + }, + "p-settle": { + "version": "4.1.1", + "requires": { + "p-limit": "^2.2.2", + "p-reflect": "^2.1.0" + }, + "dependencies": { + "p-limit": { + "version": "2.3.0", + "requires": { + "p-try": "^2.0.0" + } + } + } + }, + "p-some": { + "version": "5.0.0", + "requires": { + "aggregate-error": "^3.0.0", + "p-cancelable": "^2.0.0" + } + }, + "p-timeout": { + "version": "4.1.0" + }, + "p-times": { + "version": "3.0.0", + "requires": { + "p-map": "^4.0.0" + } + }, + "p-try": { + "version": "2.2.0" + }, + "p-wait-for": { + "version": "3.2.0", + "requires": { + "p-timeout": "^3.0.0" + }, + "dependencies": { + "p-timeout": { + "version": "3.2.0", + "requires": { + "p-finally": "^1.0.0" + } + } + } + }, + "package-hash": { + "version": "4.0.0", + "dev": true, + "requires": { + "graceful-fs": "^4.1.15", + "hasha": "^5.0.0", + "lodash.flattendeep": "^4.4.0", + "release-zalgo": "^1.0.0" + } + }, + "pad": { + "version": "3.2.0", + "dev": true, + "requires": { + "wcwidth": "^1.0.1" + } + }, + "pako": { + "version": "1.0.11", + "dev": true + }, + "parent-module": { + "version": "1.0.1", + "dev": true, + "requires": { + "callsites": "^3.0.0" + } + }, + "parents": { + "version": "1.0.1", + "dev": true, + "requires": { + "path-platform": "~0.11.15" + } + }, + "parse-asn1": { + "version": "5.1.6", + "dev": true, + "requires": { + "asn1.js": "^5.2.0", + "browserify-aes": "^1.0.0", + "evp_bytestokey": "^1.0.0", + "pbkdf2": "^3.0.3", + "safe-buffer": "^5.1.1" + } + }, + "parse-json": { + "version": "4.0.0", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "parseurl": { + "version": "1.3.3" + }, + "path-browserify": { + "version": "0.0.1", + "dev": true + }, + "path-exists": { + "version": "4.0.0", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "dev": true + }, + "path-is-inside": { + "version": "1.0.2", + "dev": true + }, + "path-key": { + "version": "3.1.1" + }, + "path-parse": { + "version": "1.0.7", + "dev": true + }, + "path-platform": { + "version": "0.11.15", + "dev": true + }, + "path-to-regexp": { + "version": "1.8.0", + "requires": { + "isarray": "0.0.1" + }, + "dependencies": { + "isarray": { + "version": "0.0.1" + } + } + }, + "path-type": { + "version": "4.0.0", + "dev": true + }, + "pathval": { + "version": "1.1.1" + }, + "pbkdf2": { + "version": "3.1.2", + "dev": true, + "requires": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "peer-id": { + "version": "0.14.8", + "requires": { + "cids": "^1.1.5", + "class-is": "^1.1.0", + "libp2p-crypto": "^0.19.0", + "minimist": "^1.2.5", + "multihashes": "^4.0.2", + "protobufjs": "^6.10.2", + "uint8arrays": "^2.0.5" + }, + "dependencies": { + "uint8arrays": { + "version": "2.1.10", + "requires": { + "multiformats": "^9.4.2" + } + } + } + }, + "pem-jwk": { + "version": "2.0.0", + "requires": { + "asn1.js": "^5.0.1" + } + }, + "perf-sym": { + "version": "2.0.3", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "minimist": "^1.2.0", + "pump": "^1.0.1", + "resolve-jit-symbols": "^0.5.0", + "split2": "^2.0.1" + }, + "dependencies": { + "pump": { + "version": "1.0.3", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "split2": { + "version": "2.2.0", + "dev": true, + "requires": { + "through2": "^2.0.2" + } + } + } + }, + "performance-now": { + "version": "2.1.0" + }, + "picocolors": { + "version": "1.0.0", + "dev": true + }, + "picomatch": { + "version": "2.3.1", + "dev": true + }, + "pidtree": { + "version": "0.6.0", + "dev": true + }, + "pify": { + "version": "3.0.0", + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "dev": true, + "requires": { + "pinkie": "^2.0.0" + } + }, + "pino": { + "version": "5.17.0", + "dev": true, + "requires": { + "fast-redact": "^2.0.0", + "fast-safe-stringify": "^2.0.7", + "flatstr": "^1.0.12", + "pino-std-serializers": "^2.4.2", + "quick-format-unescaped": "^3.0.3", + "sonic-boom": "^0.7.5" + } + }, + "pino-std-serializers": { + "version": "2.5.0", + "dev": true + }, + "pkg-conf": { + "version": "2.1.0", + "dev": true, + "requires": { + "find-up": "^2.0.0", + "load-json-file": "^4.0.0" + }, + "dependencies": { + "find-up": { + "version": "2.1.0", + "dev": true, + "requires": { + "locate-path": "^2.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "dev": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "1.3.0", + "dev": true, + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "dev": true, + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0", + "dev": true + }, + "path-exists": { + "version": "3.0.0", + "dev": true + } + } + }, + "pkg-config": { + "version": "1.1.1", + "dev": true, + "requires": { + "debug-log": "^1.0.0", + "find-root": "^1.0.0", + "xtend": "^4.0.1" + } + }, + "pkg-dir": { + "version": "4.2.0", + "dev": true, + "requires": { + "find-up": "^4.0.0" + }, + "dependencies": { + "find-up": { + "version": "4.1.0", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-limit": { + "version": "2.3.0", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + } + } + }, + "pkg-up": { + "version": "1.0.0", + "dev": true, + "requires": { + "find-up": "^1.0.0" + }, + "dependencies": { + "find-up": { + "version": "1.1.2", + "dev": true, + "requires": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "path-exists": { + "version": "2.1.0", + "dev": true, + "requires": { + "pinkie-promise": "^2.0.0" + } + } + } + }, + "platform": { + "version": "1.3.6", + "dev": true + }, + "pluralize": { + "version": "1.2.1", + "dev": true + }, + "prelude-ls": { + "version": "1.2.1", + "dev": true + }, + "prettier": { + "version": "2.7.1", + "dev": true + }, + "prettier-linter-helpers": { + "version": "1.0.0", + "dev": true, + "requires": { + "fast-diff": "^1.1.2" + } + }, + "pretty-hrtime": { + "version": "1.0.3", + "dev": true + }, + "pretty-trace": { + "version": "0.3.1", + "dev": true, + "requires": { + "ansicolors": "~0.2.1", + "split2": "~0.2.1" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "split2": { + "version": "0.2.1", + "dev": true, + "requires": { + "through2": "~0.6.1" + } + }, + "string_decoder": { + "version": "0.10.31", + "dev": true + }, + "through2": { + "version": "0.6.5", + "dev": true, + "requires": { + "readable-stream": ">=1.0.33-1 <1.1.0-0", + "xtend": ">=4.0.0 <4.1.0-0" + } + } + } + }, + "private-ip": { + "version": "2.3.4", + "requires": { + "ip-regex": "^4.3.0", + "ipaddr.js": "^2.0.1", + "is-ip": "^3.1.0", + "netmask": "^2.0.2" + } + }, + "process": { + "version": "0.11.10", + "dev": true + }, + "process-nextick-args": { + "version": "2.0.1", + "dev": true + }, + "process-on-spawn": { + "version": "1.0.0", + "dev": true, + "requires": { + "fromentries": "^1.2.0" + } + }, + "progress": { + "version": "1.1.8", + "dev": true + }, + "promise-to-callback": { + "version": "1.0.0", + "requires": { + "is-fn": "^1.0.0", + "set-immediate-shim": "^1.0.1" + } + }, + "protobufjs": { + "version": "6.11.3", + "requires": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/long": "^4.0.1", + "@types/node": ">=13.7.0", + "long": "^4.0.0" + } + }, + "protocol-buffers-schema": { + "version": "3.6.0" + }, + "protons": { + "version": "2.0.3", + "requires": { + "protocol-buffers-schema": "^3.3.1", + "signed-varint": "^2.0.1", + "uint8arrays": "^3.0.0", + "varint": "^5.0.0" + }, + "dependencies": { + "varint": { + "version": "5.0.2" + } + } + }, + "psl": { + "version": "1.9.0" + }, + "public-encrypt": { + "version": "4.0.3", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1", + "safe-buffer": "^5.1.2" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "dev": true + } + } + }, + "pump": { + "version": "3.0.0", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "pumpify": { + "version": "1.5.1", + "dev": true, + "requires": { + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" + }, + "dependencies": { + "pump": { + "version": "2.0.1", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + } + } + }, + "punycode": { + "version": "1.4.1", + "dev": true + }, + "qheap": { + "version": "1.4.0" + }, + "qjobs": { + "version": "1.2.0", + "dev": true + }, + "qs": { + "version": "6.11.0", + "requires": { + "side-channel": "^1.0.4" + } + }, + "querystring": { + "version": "0.2.0", + "dev": true + }, + "querystring-es3": { + "version": "0.2.1", + "dev": true + }, + "queue-microtask": { + "version": "1.2.3" + }, + "queue-tick": { + "version": "1.0.1", + "dev": true + }, + "quibble": { + "version": "0.6.17", + "dev": true, + "requires": { + "lodash": "^4.17.21", + "resolve": "^1.22.1" + } + }, + "quick-format-unescaped": { + "version": "3.0.3", + "dev": true + }, + "randombytes": { + "version": "2.1.0", + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "randomfill": { + "version": "1.0.4", + "dev": true, + "requires": { + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" + } + }, + "range-parser": { + "version": "1.2.1", + "dev": true + }, + "raw-body": { + "version": "2.5.1", + "requires": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + } + }, + "react-native-fetch-api": { + "version": "2.0.0", + "requires": { + "p-defer": "^3.0.0" + } + }, + "read-only-stream": { + "version": "2.0.0", + "dev": true, + "requires": { + "readable-stream": "^2.0.2" + } + }, + "readable-stream": { + "version": "2.3.7", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "readdirp": { + "version": "3.6.0", + "dev": true, + "requires": { + "picomatch": "^2.2.1" + } + }, + "readline2": { + "version": "1.0.1", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "mute-stream": "0.0.5" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "1.0.0", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + } + } + }, + "receptacle": { + "version": "1.3.2", + "requires": { + "ms": "^2.1.1" + }, + "dependencies": { + "ms": { + "version": "2.1.3" + } + } + }, + "rechoir": { + "version": "0.7.1", + "dev": true, + "requires": { + "resolve": "^1.9.0" + } + }, + "regenerate": { + "version": "1.4.2", + "dev": true + }, + "regenerate-unicode-properties": { + "version": "10.1.0", + "dev": true, + "requires": { + "regenerate": "^1.4.2" + } + }, + "regenerator-runtime": { + "version": "0.13.10", + "dev": true + }, + "regenerator-transform": { + "version": "0.15.0", + "dev": true, + "requires": { + "@babel/runtime": "^7.8.4" + } + }, + "regexp.prototype.flags": { + "version": "1.4.3", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "functions-have-names": "^1.2.2" + } + }, + "regexpp": { + "version": "3.2.0", + "dev": true + }, + "regexpu-core": { + "version": "5.2.1", + "dev": true, + "requires": { + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.1.0", + "regjsgen": "^0.7.1", + "regjsparser": "^0.9.1", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.0.0" + } + }, + "regjsgen": { + "version": "0.7.1", + "dev": true + }, + "regjsparser": { + "version": "0.9.1", + "dev": true, + "requires": { + "jsesc": "~0.5.0" + }, + "dependencies": { + "jsesc": { + "version": "0.5.0", + "dev": true + } + } + }, + "release-zalgo": { + "version": "1.0.0", + "dev": true, + "requires": { + "es6-error": "^4.0.1" + } + }, + "request": { + "version": "2.88.2", + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + }, + "dependencies": { + "qs": { + "version": "6.5.3" + }, + "uuid": { + "version": "3.4.0" + } + } + }, + "require-directory": { + "version": "2.1.1" + }, + "require-main-filename": { + "version": "2.0.0", + "dev": true + }, + "require-uncached": { + "version": "1.0.3", + "dev": true, + "requires": { + "caller-path": "^0.1.0", + "resolve-from": "^1.0.0" + }, + "dependencies": { + "resolve-from": { + "version": "1.0.1", + "dev": true + } + } + }, + "requires-port": { + "version": "1.0.0", + "dev": true + }, + "resolve": { + "version": "1.22.1", + "dev": true, + "requires": { + "is-core-module": "^2.9.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + } + }, + "resolve-cwd": { + "version": "3.0.0", + "dev": true, + "requires": { + "resolve-from": "^5.0.0" + }, + "dependencies": { + "resolve-from": { + "version": "5.0.0", + "dev": true + } + } + }, + "resolve-from": { + "version": "4.0.0", + "dev": true + }, + "resolve-jit-symbols": { + "version": "0.5.0", + "dev": true, + "requires": { + "pretty-trace": "~0.3.1" + } + }, + "restore-cursor": { + "version": "3.1.0", + "dev": true, + "requires": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + } + }, + "resumer": { + "version": "0.0.0", + "dev": true, + "requires": { + "through": "~2.3.4" + } + }, + "retimer": { + "version": "2.0.0" + }, + "retry": { + "version": "0.13.1" + }, + "reusify": { + "version": "1.0.4", + "dev": true + }, + "rfdc": { + "version": "1.3.0", + "dev": true + }, + "rimraf": { + "version": "3.0.2", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "ripemd160": { + "version": "2.0.2", + "dev": true, + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "run-async": { + "version": "0.1.0", + "dev": true, + "requires": { + "once": "^1.3.0" + } + }, + "run-parallel": { + "version": "1.2.0", + "dev": true, + "requires": { + "queue-microtask": "^1.2.2" + } + }, + "run-parallel-limit": { + "version": "1.1.0", + "requires": { + "queue-microtask": "^1.2.2" + } + }, + "rustbn.js": { + "version": "0.2.0" + }, + "rx-lite": { + "version": "3.1.2", + "dev": true + }, + "rxjs": { + "version": "7.5.7", + "dev": true, + "requires": { + "tslib": "^2.1.0" + } + }, + "safe-buffer": { + "version": "5.2.1" + }, + "safe-regex-test": { + "version": "1.0.0", + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "is-regex": "^1.1.4" + } + }, + "safe-stable-stringify": { + "version": "2.4.1" + }, + "safer-buffer": { + "version": "2.1.2" + }, + "sanitize-filename": { + "version": "1.6.3", + "requires": { + "truncate-utf8-bytes": "^1.0.0" + } + }, + "sax": { + "version": "1.2.4" + }, + "scanf": { + "version": "1.1.2" + }, + "schema-utils": { + "version": "2.7.1", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.5", + "ajv": "^6.12.4", + "ajv-keywords": "^3.5.2" + } + }, + "scrypt-js": { + "version": "3.0.1" + }, + "secp256k1": { + "version": "4.0.3", + "requires": { + "elliptic": "^6.5.4", + "node-addon-api": "^2.0.0", + "node-gyp-build": "^4.2.0" + }, + "dependencies": { + "node-addon-api": { + "version": "2.0.2" + } + } + }, + "semver": { + "version": "7.3.8", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + }, + "dependencies": { + "lru-cache": { + "version": "6.0.0", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "dev": true + } + } + }, + "serialize-javascript": { + "version": "6.0.0", + "dev": true, + "requires": { + "randombytes": "^2.1.0" + } + }, + "set-blocking": { + "version": "2.0.0", + "dev": true + }, + "set-delayed-interval": { + "version": "1.0.0" + }, + "set-immediate-shim": { + "version": "1.0.1" + }, + "setimmediate": { + "version": "1.0.5", + "dev": true + }, + "setprototypeof": { + "version": "1.2.0" + }, + "sha.js": { + "version": "2.4.11", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "shallow-clone": { + "version": "3.0.1", + "dev": true, + "requires": { + "kind-of": "^6.0.2" + } + }, + "shasum": { + "version": "1.0.2", + "dev": true, + "requires": { + "json-stable-stringify": "~0.0.0", + "sha.js": "~2.4.4" + } + }, + "shasum-object": { + "version": "1.0.0", + "dev": true, + "requires": { + "fast-safe-stringify": "^2.0.7" + } + }, + "shebang-command": { + "version": "2.0.0", + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0" + }, + "shell-quote": { + "version": "1.7.4", + "dev": true + }, + "shelljs": { + "version": "0.7.8", + "dev": true, + "requires": { + "glob": "^7.0.0", + "interpret": "^1.0.0", + "rechoir": "^0.6.2" + }, + "dependencies": { + "interpret": { + "version": "1.4.0", + "dev": true + }, + "rechoir": { + "version": "0.6.2", + "dev": true, + "requires": { + "resolve": "^1.1.6" + } + } + } + }, + "shiki": { + "version": "0.10.1", + "dev": true, + "requires": { + "jsonc-parser": "^3.0.0", + "vscode-oniguruma": "^1.6.1", + "vscode-textmate": "5.2.0" + } + }, + "side-channel": { + "version": "1.0.4", + "requires": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + } + }, + "signal-exit": { + "version": "3.0.7" + }, + "signed-varint": { + "version": "2.0.1", + "requires": { + "varint": "~5.0.0" + }, + "dependencies": { + "varint": { + "version": "5.0.2" + } + } + }, + "simple-concat": { + "version": "1.0.1", + "dev": true + }, + "simple-swizzle": { + "version": "0.2.2", + "requires": { + "is-arrayish": "^0.3.1" + }, + "dependencies": { + "is-arrayish": { + "version": "0.3.2" + } + } + }, + "single-line-log": { + "version": "1.1.2", + "dev": true, + "requires": { + "string-width": "^1.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "string-width": { + "version": "1.0.2", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + } + } + }, + "sinon": { + "version": "9.2.4", + "requires": { + "@sinonjs/commons": "^1.8.1", + "@sinonjs/fake-timers": "^6.0.1", + "@sinonjs/samsam": "^5.3.1", + "diff": "^4.0.2", + "nise": "^4.0.4", + "supports-color": "^7.1.0" + } + }, + "slash": { + "version": "3.0.0", + "dev": true + }, + "slice-ansi": { + "version": "5.0.0", + "dev": true, + "requires": { + "ansi-styles": "^6.0.0", + "is-fullwidth-code-point": "^4.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "6.2.1", + "dev": true + } + } + }, + "snappyjs": { + "version": "0.6.1" + }, + "socket.io": { + "version": "4.5.3", + "dev": true, + "requires": { + "accepts": "~1.3.4", + "base64id": "~2.0.0", + "debug": "~4.3.2", + "engine.io": "~6.2.0", + "socket.io-adapter": "~2.4.0", + "socket.io-parser": "~4.2.0" + } + }, + "socket.io-adapter": { + "version": "2.4.0", + "dev": true + }, + "socket.io-parser": { + "version": "4.2.1", + "dev": true, + "requires": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.1" + } + }, + "solc": { + "version": "0.8.17", + "dev": true, + "requires": { + "command-exists": "^1.2.8", + "commander": "^8.1.0", + "follow-redirects": "^1.12.1", + "js-sha3": "0.8.0", + "memorystream": "^0.3.1", + "semver": "^5.5.0", + "tmp": "0.0.33" + }, + "dependencies": { + "commander": { + "version": "8.3.0", + "dev": true + }, + "semver": { + "version": "5.7.1", + "dev": true + }, + "tmp": { + "version": "0.0.33", + "dev": true, + "requires": { + "os-tmpdir": "~1.0.2" + } + } + } + }, + "sonic-boom": { + "version": "0.7.7", + "dev": true, + "requires": { + "atomic-sleep": "^1.0.0", + "flatstr": "^1.0.12" + } + }, + "sort-object-keys": { + "version": "1.1.3", + "dev": true + }, + "sort-package-json": { + "version": "1.57.0", + "dev": true, + "requires": { + "detect-indent": "^6.0.0", + "detect-newline": "3.1.0", + "git-hooks-list": "1.0.3", + "globby": "10.0.0", + "is-plain-obj": "2.1.0", + "sort-object-keys": "^1.1.3" + }, + "dependencies": { + "globby": { + "version": "10.0.0", + "dev": true, + "requires": { + "@types/glob": "^7.1.1", + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.0.3", + "glob": "^7.1.3", + "ignore": "^5.1.1", + "merge2": "^1.2.3", + "slash": "^3.0.0" + } + } + } + }, + "source-map": { + "version": "0.5.7", + "dev": true + }, + "source-map-support": { + "version": "0.5.21", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "dev": true + } + } + }, + "sourcemap-codec": { + "version": "1.4.8", + "dev": true + }, + "spawn-wrap": { + "version": "2.0.0", + "dev": true, + "requires": { + "foreground-child": "^2.0.0", + "is-windows": "^1.0.2", + "make-dir": "^3.0.0", + "rimraf": "^3.0.0", + "signal-exit": "^3.0.2", + "which": "^2.0.1" + }, + "dependencies": { + "make-dir": { + "version": "3.1.0", + "dev": true, + "requires": { + "semver": "^6.0.0" + } + }, + "semver": { + "version": "6.3.0", + "dev": true + }, + "which": { + "version": "2.0.2", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "split2": { + "version": "3.2.2", + "dev": true, + "requires": { + "readable-stream": "^3.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "sprintf-js": { + "version": "1.1.2" + }, + "sshpk": { + "version": "1.17.0", + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + }, + "dependencies": { + "jsbn": { + "version": "0.1.1" + } + } + }, + "stack-trace": { + "version": "0.0.10" + }, + "standard": { + "version": "10.0.3", + "dev": true, + "requires": { + "eslint": "~3.19.0", + "eslint-config-standard": "10.2.1", + "eslint-config-standard-jsx": "4.0.2", + "eslint-plugin-import": "~2.2.0", + "eslint-plugin-node": "~4.2.2", + "eslint-plugin-promise": "~3.5.0", + "eslint-plugin-react": "~6.10.0", + "eslint-plugin-standard": "~3.0.1", + "standard-engine": "~7.0.0" + }, + "dependencies": { + "acorn": { + "version": "5.7.4", + "dev": true + }, + "acorn-jsx": { + "version": "3.0.1", + "dev": true, + "requires": { + "acorn": "^3.0.4" + }, + "dependencies": { + "acorn": { + "version": "3.3.0", + "dev": true + } + } + }, + "ansi-regex": { + "version": "2.1.1", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "dev": true + }, + "argparse": { + "version": "1.0.10", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "chalk": { + "version": "1.1.3", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "debug": { + "version": "2.6.9", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "doctrine": { + "version": "2.1.0", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "eslint": { + "version": "3.19.0", + "dev": true, + "requires": { + "babel-code-frame": "^6.16.0", + "chalk": "^1.1.3", + "concat-stream": "^1.5.2", + "debug": "^2.1.1", + "doctrine": "^2.0.0", + "escope": "^3.6.0", + "espree": "^3.4.0", + "esquery": "^1.0.0", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "file-entry-cache": "^2.0.0", + "glob": "^7.0.3", + "globals": "^9.14.0", + "ignore": "^3.2.0", + "imurmurhash": "^0.1.4", + "inquirer": "^0.12.0", + "is-my-json-valid": "^2.10.0", + "is-resolvable": "^1.0.0", + "js-yaml": "^3.5.1", + "json-stable-stringify": "^1.0.0", + "levn": "^0.3.0", + "lodash": "^4.0.0", + "mkdirp": "^0.5.0", + "natural-compare": "^1.4.0", + "optionator": "^0.8.2", + "path-is-inside": "^1.0.1", + "pluralize": "^1.2.1", + "progress": "^1.1.8", + "require-uncached": "^1.0.2", + "shelljs": "^0.7.5", + "strip-bom": "^3.0.0", + "strip-json-comments": "~2.0.1", + "table": "^3.7.8", + "text-table": "~0.2.0", + "user-home": "^2.0.0" + } + }, + "eslint-config-standard-jsx": { + "version": "4.0.2", + "dev": true, + "requires": {} + }, + "eslint-import-resolver-node": { + "version": "0.2.3", + "dev": true, + "requires": { + "debug": "^2.2.0", + "object-assign": "^4.0.1", + "resolve": "^1.1.6" + } + }, + "eslint-plugin-import": { + "version": "2.2.0", + "dev": true, + "requires": { + "builtin-modules": "^1.1.1", + "contains-path": "^0.1.0", + "debug": "^2.2.0", + "doctrine": "1.5.0", + "eslint-import-resolver-node": "^0.2.0", + "eslint-module-utils": "^2.0.0", + "has": "^1.0.1", + "lodash.cond": "^4.3.0", + "minimatch": "^3.0.3", + "pkg-up": "^1.0.0" + }, + "dependencies": { + "doctrine": { + "version": "1.5.0", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "isarray": "^1.0.0" + } + } + } + }, + "eslint-plugin-react": { + "version": "6.10.3", + "dev": true, + "requires": { + "array.prototype.find": "^2.0.1", + "doctrine": "^1.2.2", + "has": "^1.0.1", + "jsx-ast-utils": "^1.3.4", + "object.assign": "^4.0.4" + }, + "dependencies": { + "doctrine": { + "version": "1.5.0", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "isarray": "^1.0.0" + } + } + } + }, + "espree": { + "version": "3.5.4", + "dev": true, + "requires": { + "acorn": "^5.5.0", + "acorn-jsx": "^3.0.0" + } + }, + "file-entry-cache": { + "version": "2.0.0", + "dev": true, + "requires": { + "flat-cache": "^1.2.1", + "object-assign": "^4.0.1" + } + }, + "flat-cache": { + "version": "1.3.4", + "dev": true, + "requires": { + "circular-json": "^0.3.1", + "graceful-fs": "^4.1.2", + "rimraf": "~2.6.2", + "write": "^0.2.1" + } + }, + "globals": { + "version": "9.18.0", + "dev": true + }, + "ignore": { + "version": "3.3.10", + "dev": true + }, + "js-yaml": { + "version": "3.14.1", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "json-stable-stringify": { + "version": "1.0.1", + "dev": true, + "requires": { + "jsonify": "~0.0.0" + } + }, + "jsx-ast-utils": { + "version": "1.4.1", + "dev": true + }, + "levn": { + "version": "0.3.0", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "ms": { + "version": "2.0.0", + "dev": true + }, + "optionator": { + "version": "0.8.3", + "dev": true, + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + } + }, + "prelude-ls": { + "version": "1.1.2", + "dev": true + }, + "rimraf": { + "version": "2.6.3", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "sprintf-js": { + "version": "1.0.3", + "dev": true + }, + "strip-ansi": { + "version": "3.0.1", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-bom": { + "version": "3.0.0", + "dev": true + }, + "strip-json-comments": { + "version": "2.0.1", + "dev": true + }, + "supports-color": { + "version": "2.0.0", + "dev": true + }, + "type-check": { + "version": "0.3.2", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2" + } + } + } + }, + "standard-engine": { + "version": "7.0.0", + "dev": true, + "requires": { + "deglob": "^2.1.0", + "get-stdin": "^5.0.1", + "minimist": "^1.1.0", + "pkg-conf": "^2.0.0" + } + }, + "statuses": { + "version": "1.5.0" + }, + "stream-browserify": { + "version": "3.0.0", + "dev": true, + "requires": { + "inherits": "~2.0.4", + "readable-stream": "^3.5.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "stream-combiner2": { + "version": "1.1.1", + "dev": true, + "requires": { + "duplexer2": "~0.1.0", + "readable-stream": "^2.0.2" + } + }, + "stream-http": { + "version": "3.2.0", + "dev": true, + "requires": { + "builtin-status-codes": "^3.0.0", + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "xtend": "^4.0.2" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "stream-shift": { + "version": "1.0.1", + "dev": true + }, + "stream-splicer": { + "version": "2.0.1", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.2" + } + }, + "stream-to-it": { + "version": "0.2.4", + "requires": { + "get-iterator": "^1.0.2" + } + }, + "streaming-iterables": { + "version": "5.0.4" + }, + "streamroller": { + "version": "3.1.3", + "dev": true, + "requires": { + "date-format": "^4.0.14", + "debug": "^4.3.4", + "fs-extra": "^8.1.0" + }, + "dependencies": { + "fs-extra": { + "version": "8.1.0", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "jsonfile": { + "version": "4.0.0", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "universalify": { + "version": "0.1.2", + "dev": true + } + } + }, + "string_decoder": { + "version": "1.3.0", + "requires": { + "safe-buffer": "~5.2.0" + } + }, + "string-argv": { + "version": "0.3.1", + "dev": true + }, + "string-width": { + "version": "5.1.2", + "dev": true, + "requires": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "6.0.1", + "dev": true + }, + "strip-ansi": { + "version": "7.0.1", + "dev": true, + "requires": { + "ansi-regex": "^6.0.1" + } + } + } + }, + "string.prototype.trim": { + "version": "1.2.6", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.19.5" + } + }, + "string.prototype.trimend": { + "version": "1.0.5", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.19.5" + } + }, + "string.prototype.trimstart": { + "version": "1.0.5", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.19.5" + } + }, + "stringify-object-es5": { + "version": "2.5.0", + "dev": true, + "requires": { + "is-plain-obj": "^1.0.0", + "is-regexp": "^1.0.0" + }, + "dependencies": { + "is-plain-obj": { + "version": "1.1.0", + "dev": true + } + } + }, + "strip-ansi": { + "version": "6.0.1", + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "strip-bom": { + "version": "4.0.0", + "dev": true + }, + "strip-final-newline": { + "version": "2.0.0" + }, + "strip-json-comments": { + "version": "3.1.1", + "dev": true + }, + "subarg": { + "version": "1.0.0", + "dev": true, + "requires": { + "minimist": "^1.1.0" + } + }, + "superagent": { + "version": "8.0.2", + "dev": true, + "requires": { + "component-emitter": "^1.3.0", + "cookiejar": "^2.1.3", + "debug": "^4.3.4", + "fast-safe-stringify": "^2.1.1", + "form-data": "^4.0.0", + "formidable": "^2.0.1", + "methods": "^1.1.2", + "mime": "2.6.0", + "qs": "^6.11.0", + "semver": "^7.3.7" + }, + "dependencies": { + "form-data": { + "version": "4.0.0", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + } + } + }, + "supertest": { + "version": "6.3.0", + "dev": true, + "requires": { + "methods": "^1.1.2", + "superagent": "^8.0.0" + } + }, + "superwstest": { + "version": "2.0.3", + "dev": true, + "requires": { + "@types/supertest": "<7", + "@types/ws": "7.x || 8.x", + "ws": "7.x || 8.x" + } + }, + "supports-color": { + "version": "7.2.0", + "requires": { + "has-flag": "^4.0.0" + } + }, + "supports-preserve-symlinks-flag": { + "version": "1.0.0", + "dev": true + }, + "svg-element-attributes": { + "version": "1.3.1", + "dev": true + }, + "syntax-error": { + "version": "1.4.0", + "dev": true, + "requires": { + "acorn-node": "^1.2.0" + } + }, + "table": { + "version": "3.8.3", + "dev": true, + "requires": { + "ajv": "^4.7.0", + "ajv-keywords": "^1.0.0", + "chalk": "^1.1.1", + "lodash": "^4.0.0", + "slice-ansi": "0.0.4", + "string-width": "^2.0.0" + }, + "dependencies": { + "ajv": { + "version": "4.11.8", + "dev": true, + "requires": { + "co": "^4.6.0", + "json-stable-stringify": "^1.0.1" + } + }, + "ajv-keywords": { + "version": "1.5.1", + "dev": true, + "requires": {} + }, + "ansi-regex": { + "version": "2.1.1", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "dev": true + }, + "json-stable-stringify": { + "version": "1.0.1", + "dev": true, + "requires": { + "jsonify": "~0.0.0" + } + }, + "slice-ansi": { + "version": "0.0.4", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.1", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "strip-ansi": { + "version": "3.0.1", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "dev": true + } + } + }, + "tachyons": { + "version": "4.12.0", + "dev": true + }, + "tapable": { + "version": "2.2.1", + "dev": true + }, + "tape": { + "version": "5.6.0", + "dev": true, + "requires": { + "array.prototype.every": "^1.1.3", + "call-bind": "^1.0.2", + "deep-equal": "^2.0.5", + "defined": "^1.0.0", + "dotignore": "^0.1.2", + "for-each": "^0.3.3", + "get-package-type": "^0.1.0", + "glob": "^7.2.3", + "has": "^1.0.3", + "has-dynamic-import": "^2.0.1", + "inherits": "^2.0.4", + "is-regex": "^1.1.4", + "minimist": "^1.2.6", + "object-inspect": "^1.12.2", + "object-is": "^1.1.5", + "object-keys": "^1.1.1", + "object.assign": "^4.1.3", + "resolve": "^2.0.0-next.3", + "resumer": "^0.0.0", + "string.prototype.trim": "^1.2.6", + "through": "^2.3.8" + }, + "dependencies": { + "resolve": { + "version": "2.0.0-next.4", + "dev": true, + "requires": { + "is-core-module": "^2.9.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + } + } + } + }, + "terser": { + "version": "5.15.1", + "dev": true, + "requires": { + "@jridgewell/source-map": "^0.3.2", + "acorn": "^8.5.0", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "dependencies": { + "commander": { + "version": "2.20.3", + "dev": true + } + } + }, + "terser-webpack-plugin": { + "version": "5.3.6", + "dev": true, + "requires": { + "@jridgewell/trace-mapping": "^0.3.14", + "jest-worker": "^27.4.5", + "schema-utils": "^3.1.1", + "serialize-javascript": "^6.0.0", + "terser": "^5.14.1" + }, + "dependencies": { + "schema-utils": { + "version": "3.1.1", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + } + } + }, + "test-exclude": { + "version": "6.0.0", + "dev": true, + "requires": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + } + }, + "testdouble": { + "version": "3.17.2", + "dev": true, + "requires": { + "lodash": "^4.17.21", + "quibble": "^0.6.17", + "stringify-object-es5": "^2.5.0", + "theredoc": "^1.0.0" + } + }, + "testdouble-timers": { + "version": "0.1.1", + "dev": true, + "requires": { + "lolex": "^1.4.0" + } + }, + "text-hex": { + "version": "1.0.0" + }, + "text-table": { + "version": "0.2.0", + "dev": true + }, + "theredoc": { + "version": "1.0.0", + "dev": true + }, + "through": { + "version": "2.3.8" + }, + "through2": { + "version": "2.0.5", + "dev": true, + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "timeout-abort-controller": { + "version": "1.1.1", + "requires": { + "abort-controller": "^3.0.0", + "retimer": "^2.0.0" + } + }, + "timers-browserify": { + "version": "1.4.2", + "dev": true, + "requires": { + "process": "~0.11.0" + } + }, + "tmp": { + "version": "0.2.1", + "dev": true, + "requires": { + "rimraf": "^3.0.0" + } + }, + "to-fast-properties": { + "version": "2.0.0", + "dev": true + }, + "to-regex-range": { + "version": "5.0.1", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, + "toidentifier": { + "version": "1.0.1" + }, + "tough-cookie": { + "version": "2.5.0", + "requires": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + }, + "dependencies": { + "punycode": { + "version": "2.1.1" + } + } + }, + "tr46": { + "version": "0.0.3" + }, + "transform-ast": { + "version": "2.4.4", + "dev": true, + "requires": { + "acorn-node": "^1.3.0", + "convert-source-map": "^1.5.1", + "dash-ast": "^1.0.0", + "is-buffer": "^2.0.0", + "magic-string": "^0.23.2", + "merge-source-map": "1.0.4", + "nanobench": "^2.1.1" + }, + "dependencies": { + "convert-source-map": { + "version": "1.9.0", + "dev": true + }, + "magic-string": { + "version": "0.23.2", + "dev": true, + "requires": { + "sourcemap-codec": "^1.4.1" + } + } + } + }, + "triple-beam": { + "version": "1.3.0" + }, + "truncate-utf8-bytes": { + "version": "1.0.2", + "requires": { + "utf8-byte-length": "^1.0.1" + } + }, + "ts-node": { + "version": "10.9.1", + "dev": true, + "requires": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "dependencies": { + "acorn-walk": { + "version": "8.2.0", + "dev": true + } + } + }, + "tsconfig-paths": { + "version": "3.14.1", + "dev": true, + "requires": { + "@types/json5": "^0.0.29", + "json5": "^1.0.1", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + }, + "dependencies": { + "json5": { + "version": "1.0.1", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "strip-bom": { + "version": "3.0.0", + "dev": true + } + } + }, + "tslib": { + "version": "2.4.0", + "dev": true + }, + "tsutils": { + "version": "3.21.0", + "dev": true, + "requires": { + "tslib": "^1.8.1" + }, + "dependencies": { + "tslib": { + "version": "1.14.1", + "dev": true + } + } + }, + "tty-browserify": { + "version": "0.0.1", + "dev": true + }, + "tunnel-agent": { + "version": "0.6.0", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5" + }, + "type": { + "version": "1.2.0", + "dev": true + }, + "type-check": { + "version": "0.4.0", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1" + } + }, + "type-component": { + "version": "0.0.1", + "dev": true + }, + "type-detect": { + "version": "4.0.8" + }, + "type-fest": { + "version": "0.20.2", + "dev": true + }, + "type-is": { + "version": "1.6.18", + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + } + }, + "typedarray": { + "version": "0.0.6", + "dev": true + }, + "typedarray-to-buffer": { + "version": "3.1.5", + "dev": true, + "requires": { + "is-typedarray": "^1.0.0" + } + }, + "typedoc": { + "version": "0.23.10", + "dev": true, + "requires": { + "lunr": "^2.3.9", + "marked": "^4.0.18", + "minimatch": "^5.1.0", + "shiki": "^0.10.1" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "minimatch": { + "version": "5.1.0", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + } + } + }, + "typedoc-plugin-markdown": { + "version": "3.13.4", + "dev": true, + "requires": { + "handlebars": "^4.7.7" + } + }, + "typescript": { + "version": "4.7.4", + "dev": true + }, + "ua-parser-js": { + "version": "0.7.32", + "dev": true + }, + "uglify-js": { + "version": "3.17.3", + "dev": true, + "optional": true + }, + "uint8arrays": { + "version": "3.1.1", + "requires": { + "multiformats": "^9.4.2" + } + }, + "umd": { + "version": "3.0.3", + "dev": true + }, + "unbox-primitive": { + "version": "1.0.2", + "requires": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + } + }, + "undeclared-identifiers": { + "version": "1.1.3", + "dev": true, + "requires": { + "acorn-node": "^1.3.0", + "dash-ast": "^1.0.0", + "get-assigned-identifiers": "^1.2.0", + "simple-concat": "^1.0.0", + "xtend": "^4.0.1" + } + }, + "unicode-canonical-property-names-ecmascript": { + "version": "2.0.0", + "dev": true + }, + "unicode-match-property-ecmascript": { + "version": "2.0.0", + "dev": true, + "requires": { + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" + } + }, + "unicode-match-property-value-ecmascript": { + "version": "2.0.0", + "dev": true + }, + "unicode-property-aliases-ecmascript": { + "version": "2.1.0", + "dev": true + }, + "uniq": { + "version": "1.0.1", + "dev": true + }, + "universalify": { + "version": "2.0.0" + }, + "unordered-array-remove": { + "version": "1.0.2" + }, + "unpipe": { + "version": "1.0.0" + }, + "update-browserslist-db": { + "version": "1.0.10", + "dev": true, + "requires": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + } + }, + "upper-case": { + "version": "1.1.3", + "dev": true + }, + "uri-js": { + "version": "4.4.1", + "requires": { + "punycode": "^2.1.0" + }, + "dependencies": { + "punycode": { + "version": "2.1.1" + } + } + }, + "url": { + "version": "0.11.0", + "dev": true, + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + }, + "dependencies": { + "punycode": { + "version": "1.3.2", + "dev": true + } + } + }, + "ursa-optional": { + "version": "0.10.2", + "requires": { + "bindings": "^1.5.0", + "nan": "^2.14.2" + } + }, + "user-home": { + "version": "2.0.0", + "dev": true, + "requires": { + "os-homedir": "^1.0.0" + } + }, + "utf8-byte-length": { + "version": "1.0.4" + }, + "util": { + "version": "0.12.5", + "requires": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "which-typed-array": "^1.1.2" + } + }, + "util-deprecate": { + "version": "1.0.2" + }, + "util-extend": { + "version": "1.0.3", + "dev": true + }, + "utils-merge": { + "version": "1.0.1" + }, + "uuid": { + "version": "8.3.2" + }, + "v8-compile-cache": { + "version": "2.3.0", + "dev": true + }, + "v8-compile-cache-lib": { + "version": "3.0.1", + "dev": true + }, + "v8-to-istanbul": { + "version": "9.0.1", + "dev": true, + "requires": { + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^1.6.0" + }, + "dependencies": { + "convert-source-map": { + "version": "1.9.0", + "dev": true + } + } + }, + "varint": { + "version": "6.0.0" + }, + "vary": { + "version": "1.1.2" + }, + "verror": { + "version": "1.10.0", + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + }, + "dependencies": { + "core-util-is": { + "version": "1.0.2" + } + } + }, + "vm-browserify": { + "version": "1.1.2", + "dev": true + }, + "void-elements": { + "version": "2.0.1", + "dev": true + }, + "vscode-oniguruma": { + "version": "1.6.2", + "dev": true + }, + "vscode-textmate": { + "version": "5.2.0", + "dev": true + }, + "watchpack": { + "version": "2.4.0", + "dev": true, + "requires": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + } + }, + "wcwidth": { + "version": "1.0.1", + "dev": true, + "requires": { + "defaults": "^1.0.3" + } + }, + "weak-lru-cache": { + "version": "1.2.2", + "dev": true + }, + "web-encoding": { + "version": "1.1.5", + "requires": { + "@zxing/text-encoding": "0.9.0", + "util": "^0.12.3" + } + }, + "webidl-conversions": { + "version": "3.0.1" + }, + "webpack": { + "version": "5.74.0", + "dev": true, + "requires": { + "@types/eslint-scope": "^3.7.3", + "@types/estree": "^0.0.51", + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/wasm-edit": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1", + "acorn": "^8.7.1", + "acorn-import-assertions": "^1.7.6", + "browserslist": "^4.14.5", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.10.0", + "es-module-lexer": "^0.9.0", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.9", + "json-parse-even-better-errors": "^2.3.1", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^3.1.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.1.3", + "watchpack": "^2.4.0", + "webpack-sources": "^3.2.3" + }, + "dependencies": { + "events": { + "version": "3.3.0", + "dev": true + }, + "schema-utils": { + "version": "3.1.1", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + } + } + }, + "webpack-cli": { + "version": "4.10.0", + "dev": true, + "requires": { + "@discoveryjs/json-ext": "^0.5.0", + "@webpack-cli/configtest": "^1.2.0", + "@webpack-cli/info": "^1.5.0", + "@webpack-cli/serve": "^1.7.0", + "colorette": "^2.0.14", + "commander": "^7.0.0", + "cross-spawn": "^7.0.3", + "fastest-levenshtein": "^1.0.12", + "import-local": "^3.0.2", + "interpret": "^2.2.0", + "rechoir": "^0.7.0", + "webpack-merge": "^5.7.3" + }, + "dependencies": { + "commander": { + "version": "7.2.0", + "dev": true + } + } + }, + "webpack-merge": { + "version": "5.8.0", + "dev": true, + "requires": { + "clone-deep": "^4.0.1", + "wildcard": "^2.0.0" + } + }, + "webpack-sources": { + "version": "3.2.3", + "dev": true + }, + "whatwg-url": { + "version": "5.0.0", + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "which": { + "version": "1.3.1", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "which-boxed-primitive": { + "version": "1.0.2", + "requires": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + } + }, + "which-collection": { + "version": "1.0.1", + "dev": true, + "requires": { + "is-map": "^2.0.1", + "is-set": "^2.0.1", + "is-weakmap": "^2.0.1", + "is-weakset": "^2.0.1" + } + }, + "which-module": { + "version": "2.0.0", + "dev": true + }, + "which-typed-array": { + "version": "1.1.8", + "requires": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "es-abstract": "^1.20.0", + "for-each": "^0.3.3", + "has-tostringtag": "^1.0.0", + "is-typed-array": "^1.1.9" + } + }, + "wildcard": { + "version": "2.0.0", + "dev": true + }, + "winston": { + "version": "3.8.2", + "requires": { + "@colors/colors": "1.5.0", + "@dabh/diagnostics": "^2.0.2", + "async": "^3.2.3", + "is-stream": "^2.0.0", + "logform": "^2.4.0", + "one-time": "^1.0.0", + "readable-stream": "^3.4.0", + "safe-stable-stringify": "^2.3.1", + "stack-trace": "0.0.x", + "triple-beam": "^1.3.0", + "winston-transport": "^4.5.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "winston-daily-rotate-file": { + "version": "4.7.1", + "requires": { + "file-stream-rotator": "^0.6.1", + "object-hash": "^2.0.1", + "triple-beam": "^1.3.0", + "winston-transport": "^4.4.0" + } + }, + "winston-transport": { + "version": "4.5.0", + "requires": { + "logform": "^2.3.2", + "readable-stream": "^3.6.0", + "triple-beam": "^1.3.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "word-wrap": { + "version": "1.2.3", + "dev": true + }, + "wordwrap": { + "version": "1.0.0", + "dev": true + }, + "wrap-ansi": { + "version": "7.0.0", + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "emoji-regex": { + "version": "8.0.0" + }, + "is-fullwidth-code-point": { + "version": "3.0.0" + }, + "string-width": { + "version": "4.2.3", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + } + } + }, + "wrappy": { + "version": "1.0.2", + "dev": true + }, + "write": { + "version": "0.2.1", + "dev": true, + "requires": { + "mkdirp": "^0.5.1" + } + }, + "write-file-atomic": { + "version": "3.0.3", + "dev": true, + "requires": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + }, + "ws": { + "version": "7.5.9", + "requires": {} + }, + "xml2js": { + "version": "0.4.23", + "requires": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + } + }, + "xmlbuilder": { + "version": "11.0.1" + }, + "xor-distance": { + "version": "2.0.0" + }, + "xsalsa20": { + "version": "1.2.0" + }, + "xtend": { + "version": "4.0.2", + "dev": true + }, + "y18n": { + "version": "5.0.8" + }, + "yaml": { + "version": "2.1.3", + "dev": true + }, + "yargs": { + "version": "16.2.0", + "dev": true, + "requires": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "dependencies": { + "emoji-regex": { + "version": "8.0.0", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "dev": true + }, + "string-width": { + "version": "4.2.3", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + } + } + }, + "yargs-parser": { + "version": "20.2.9", + "dev": true + }, + "yn": { + "version": "3.1.1", + "dev": true + }, + "yocto-queue": { + "version": "0.1.0" + } + } +} From 69d64a1c66195aae4593bdb9e078411b4a775dc0 Mon Sep 17 00:00:00 2001 From: acolytec3 <17355484+acolytec3@users.noreply.github.com> Date: Fri, 12 May 2023 11:33:23 -0400 Subject: [PATCH 51/53] lint --- packages/statemanager/src/ethersStateManager.ts | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/packages/statemanager/src/ethersStateManager.ts b/packages/statemanager/src/ethersStateManager.ts index 1cc930c3ae..7674f9f71c 100644 --- a/packages/statemanager/src/ethersStateManager.ts +++ b/packages/statemanager/src/ethersStateManager.ts @@ -347,31 +347,29 @@ export class EthersStateManager implements EVMStateManagerInterface { getOriginalContractStorage(_address: Address, _key: Uint8Array): Promise { throw new Error('function not implemented') } - clearWarmedAccounts(): void { - // throw new Error('function not implemented') - } + clearWarmedAccounts(): void {} cleanupTouchedAccounts(): Promise { return Promise.resolve() } clearOriginalStorageCache(): void { // throw new Error('function not implemented') } - addWarmedAddress(address: Uint8Array): void { + addWarmedAddress(_address: Uint8Array): void { // throw new Error('function not implemented') } - isWarmedAddress(address: Uint8Array): boolean { + isWarmedAddress(_address: Uint8Array): boolean { throw new Error('function not implemented') } - addWarmedStorage(address: Uint8Array, slot: Uint8Array): void { + addWarmedStorage(_address: Uint8Array, _slot: Uint8Array): void { // throw new Error('function not implemented') } - isWarmedStorage(address: Uint8Array, slot: Uint8Array): boolean { + isWarmedStorage(_address: Uint8Array, _slot: Uint8Array): boolean { throw new Error('function not implemented') } generateCanonicalGenesis(_initState: any): Promise { return Promise.resolve() } - generateAccessList(addressesRemoved: Address[], addressesOnlyStorage: Address[]): AccessList { + generateAccessList(_addressesRemoved: Address[], _addressesOnlyStorage: Address[]): AccessList { throw new Error('function not implemented') } } From 6dfe1df42145324fd6e2ac0bec18018ae74b6583 Mon Sep 17 00:00:00 2001 From: acolytec3 <17355484+acolytec3@users.noreply.github.com> Date: Fri, 12 May 2023 11:49:30 -0400 Subject: [PATCH 52/53] Fix browser stuff --- packages/block/karma.conf.js | 1 + packages/evm/karma.conf.js | 1 + .../precompiles/14-pointevaluation.spec.ts | 162 +++++++++--------- packages/tx/karma.conf.js | 1 + 4 files changed, 86 insertions(+), 79 deletions(-) diff --git a/packages/block/karma.conf.js b/packages/block/karma.conf.js index 3cdcf9821e..f1ad097975 100644 --- a/packages/block/karma.conf.js +++ b/packages/block/karma.conf.js @@ -13,6 +13,7 @@ module.exports = function (config) { acornOptions: { ecmaVersion: 12, }, + ignore: ['c-kzg'], }, }, concurrency: 1, diff --git a/packages/evm/karma.conf.js b/packages/evm/karma.conf.js index 1f9879793c..c79a1f1453 100644 --- a/packages/evm/karma.conf.js +++ b/packages/evm/karma.conf.js @@ -31,6 +31,7 @@ module.exports = function (config) { 'bigint-crypto-utils': '../../node_modules/bigint-crypto-utils/dist/bundle.umd.js', }, }, + ignore: ['c-kzg'], }, }, diff --git a/packages/evm/test/precompiles/14-pointevaluation.spec.ts b/packages/evm/test/precompiles/14-pointevaluation.spec.ts index 06424ec44f..981216668e 100644 --- a/packages/evm/test/precompiles/14-pointevaluation.spec.ts +++ b/packages/evm/test/precompiles/14-pointevaluation.spec.ts @@ -16,92 +16,96 @@ import { EVM, getActivePrecompiles } from '../../src' import { BLS_MODULUS } from '../../src/precompiles/14-kzg-point-evaluation' import type { PrecompileInput } from '../../src/precompiles' - -initKZG(kzg, __dirname + '/../../../client/lib/trustedSetups/devnet4.txt') +const isBrowser = new Function('try {return this===window;}catch(e){ return false;}') tape('Precompiles: point evaluation', async (t) => { - const genesisJSON = require('../../../client/test/testdata/geth-genesis/eip4844.json') - const common = Common.fromGethGenesis(genesisJSON, { - chain: 'custom', - hardfork: Hardfork.Cancun, - }) - const evm = await EVM.create({ - common, - stateManager: new DefaultStateManager(), - }) - const addressStr = '0000000000000000000000000000000000000014' - const pointEvaluation = getActivePrecompiles(common).get(addressStr)! + if (isBrowser() === true) { + t.end() + } else { + initKZG(kzg, __dirname + '/../../../client/lib/trustedSetups/devnet4.txt') + const genesisJSON = require('../../../client/test/testdata/geth-genesis/eip4844.json') + const common = Common.fromGethGenesis(genesisJSON, { + chain: 'custom', + hardfork: Hardfork.Cancun, + }) + const evm = await EVM.create({ + common, + stateManager: new DefaultStateManager(), + }) + const addressStr = '0000000000000000000000000000000000000014' + const pointEvaluation = getActivePrecompiles(common).get(addressStr)! - const testCase = { - Proof: hexToBytes( - '8ad6f539bc7280de6af4c95e7cef39bb6873f18c46ee5eb67299324ee7c6e6da71be2dbd5e2cbafbae4b2d60b40a808c' - ), - Commitment: hexToBytes( - 'abb6bcbe313530ce7779abdf633d5a3594a41fbad9a79f4a9b46b89c0cfe78f6a15948dec92c4404aedac8b5e7dd6059' - ), - InputPoint: hexToBytes('0120000000000000000000000000000000000000000000000000000000000000'), - ClaimedValue: hexToBytes('48cdd065593bd932707001e88674108ade9dd71d2e849e9a55fa71b70f06690f'), - } - const versionedHash = computeVersionedHash(testCase.Commitment, 1) + const testCase = { + Proof: hexToBytes( + '8ad6f539bc7280de6af4c95e7cef39bb6873f18c46ee5eb67299324ee7c6e6da71be2dbd5e2cbafbae4b2d60b40a808c' + ), + Commitment: hexToBytes( + 'abb6bcbe313530ce7779abdf633d5a3594a41fbad9a79f4a9b46b89c0cfe78f6a15948dec92c4404aedac8b5e7dd6059' + ), + InputPoint: hexToBytes('0120000000000000000000000000000000000000000000000000000000000000'), + ClaimedValue: hexToBytes('48cdd065593bd932707001e88674108ade9dd71d2e849e9a55fa71b70f06690f'), + } + const versionedHash = computeVersionedHash(testCase.Commitment, 1) - const opts: PrecompileInput = { - data: concatBytesNoTypeCheck( - versionedHash, - testCase.InputPoint, - testCase.ClaimedValue, - testCase.Commitment, - testCase.Proof - ), - gasLimit: 0xfffffffffn, - _EVM: evm, - _common: common, - } + const opts: PrecompileInput = { + data: concatBytesNoTypeCheck( + versionedHash, + testCase.InputPoint, + testCase.ClaimedValue, + testCase.Commitment, + testCase.Proof + ), + gasLimit: 0xfffffffffn, + _EVM: evm, + _common: common, + } - let res = await pointEvaluation(opts) - t.equal( - bytesToBigInt(unpadBytes(res.returnValue.slice(32))), - BLS_MODULUS, - 'point evaluation precompile returned expected output' - ) + let res = await pointEvaluation(opts) + t.equal( + bytesToBigInt(unpadBytes(res.returnValue.slice(32))), + BLS_MODULUS, + 'point evaluation precompile returned expected output' + ) - const optsWithBigNumbers: PrecompileInput = { - data: concatBytesNoTypeCheck( - versionedHash, - testCase.InputPoint, - bigIntToBytes(BLS_MODULUS + 5n), - testCase.Commitment, - testCase.Proof - ), - gasLimit: 0xfffffffffn, - _EVM: evm, - _common: common, - } + const optsWithBigNumbers: PrecompileInput = { + data: concatBytesNoTypeCheck( + versionedHash, + testCase.InputPoint, + bigIntToBytes(BLS_MODULUS + 5n), + testCase.Commitment, + testCase.Proof + ), + gasLimit: 0xfffffffffn, + _EVM: evm, + _common: common, + } - res = await pointEvaluation(optsWithBigNumbers) - t.equal( - res.exceptionError?.error, - 'point greater than BLS modulus', - 'point evaluation precompile throws when points are too big' - ) + res = await pointEvaluation(optsWithBigNumbers) + t.equal( + res.exceptionError?.error, + 'point greater than BLS modulus', + 'point evaluation precompile throws when points are too big' + ) - const optsWithInvalidCommitment: PrecompileInput = { - data: concatBytesNoTypeCheck( - concatBytesNoTypeCheck(Uint8Array.from([0]), versionedHash.slice(1)), - testCase.InputPoint, - testCase.ClaimedValue, - testCase.Commitment, - testCase.Proof - ), - gasLimit: 0xfffffffffn, - _EVM: evm, - _common: common, - } + const optsWithInvalidCommitment: PrecompileInput = { + data: concatBytesNoTypeCheck( + concatBytesNoTypeCheck(Uint8Array.from([0]), versionedHash.slice(1)), + testCase.InputPoint, + testCase.ClaimedValue, + testCase.Commitment, + testCase.Proof + ), + gasLimit: 0xfffffffffn, + _EVM: evm, + _common: common, + } - res = await pointEvaluation(optsWithInvalidCommitment) - t.equal( - res.exceptionError?.error, - 'kzg commitment does not match versioned hash', - 'precompile throws when commitment doesnt match versioned hash' - ) - t.end() + res = await pointEvaluation(optsWithInvalidCommitment) + t.equal( + res.exceptionError?.error, + 'kzg commitment does not match versioned hash', + 'precompile throws when commitment doesnt match versioned hash' + ) + t.end() + } }) diff --git a/packages/tx/karma.conf.js b/packages/tx/karma.conf.js index 5f921f9078..837089c906 100644 --- a/packages/tx/karma.conf.js +++ b/packages/tx/karma.conf.js @@ -15,6 +15,7 @@ module.exports = function (config) { acornOptions: { ecmaVersion: 12, }, + ignore: ['c-kzg', 'safer-buffer'], }, }, browsers: ['FirefoxHeadless', 'ChromeHeadless'], From 6bc6a109fd7d4ff793b19b21721d1418f9ef5fe1 Mon Sep 17 00:00:00 2001 From: acolytec3 <17355484+acolytec3@users.noreply.github.com> Date: Fri, 12 May 2023 12:33:52 -0400 Subject: [PATCH 53/53] Move browsercheck function to EVM --- packages/evm/test/precompiles/eip-2537-BLS.spec.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/packages/evm/test/precompiles/eip-2537-BLS.spec.ts b/packages/evm/test/precompiles/eip-2537-BLS.spec.ts index b272c282d5..a4f554e05d 100644 --- a/packages/evm/test/precompiles/eip-2537-BLS.spec.ts +++ b/packages/evm/test/precompiles/eip-2537-BLS.spec.ts @@ -4,7 +4,6 @@ import { Address, bytesToPrefixedHexString } from '@ethereumjs/util' import { hexToBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' -import { isRunningInKarma } from '../../../vm/test/util' import { getActivePrecompiles } from '../../src' import { EVM } from '../../src/evm' @@ -13,6 +12,15 @@ const precompileAddressEnd = 0x12 const precompiles: string[] = [] +/** + * Checks if in a karma test runner. + * @returns boolean whether running in karma + */ +export function isRunningInKarma(): boolean { + // eslint-disable-next-line no-undef + return typeof (globalThis).window !== 'undefined' && (globalThis).window.__karma__ +} + for (let address = precompileAddressStart; address <= precompileAddressEnd; address++) { precompiles.push(address.toString(16).padStart(40, '0')) }