From 8de1a5d0ab8c16d17749fd3ca3cbdaf5e3539162 Mon Sep 17 00:00:00 2001 From: Holger Drewes Date: Thu, 15 Aug 2024 15:48:50 +0200 Subject: [PATCH] Rebuild examples --- packages/block/README.md | 76 ++++++++++++------------- packages/blockchain/README.md | 27 ++++----- packages/common/README.md | 2 - packages/devp2p/README.md | 26 ++++----- packages/ethash/README.md | 18 +++--- packages/evm/README.md | 42 +++++++------- packages/genesis/README.md | 6 +- packages/rlp/README.md | 2 +- packages/statemanager/README.md | 59 +++++++++----------- packages/trie/README.md | 70 ++++++++++++----------- packages/tx/README.md | 75 ++++++++++++------------- packages/util/README.md | 8 +-- packages/vm/README.md | 98 ++++++++++++++++++--------------- packages/wallet/README.md | 10 ++-- 14 files changed, 266 insertions(+), 253 deletions(-) diff --git a/packages/block/README.md b/packages/block/README.md index c78a8be8ace..a51de45d02b 100644 --- a/packages/block/README.md +++ b/packages/block/README.md @@ -40,16 +40,18 @@ Instantiation Example: ```ts // ./examples/simple.ts -import { BlockHeader } from '@ethereumjs/block' +import { createBlockHeader } from '@ethereumjs/block' import { bytesToHex } from '@ethereumjs/util' -const headerData = { +import type { HeaderData } from '@ethereumjs/block' + +const headerData: HeaderData = { number: 15, parentHash: '0x6bfee7294bf44572b7266358e627f3c35105e1c3851f3de09e6d646f955725a7', gasLimit: 8000000, timestamp: 1562422144, } -const header = BlockHeader.fromHeaderData(headerData) +const header = createBlockHeader(headerData) console.log(`Created block header with hash=${bytesToHex(header.hash())}`) ``` @@ -77,11 +79,11 @@ This library supports the creation of [EIP-1559](https://eips.ethereum.org/EIPS/ ```ts // ./examples/1559.ts -import { Block } from '@ethereumjs/block' -import { Chain, Common, Hardfork } from '@ethereumjs/common' -const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.London }) +import { createBlock } from '@ethereumjs/block' +import { Common, Hardfork, Mainnet } from '@ethereumjs/common' +const common = new Common({ chain: Mainnet, hardfork: Hardfork.London }) -const block = Block.fromBlockData( +const block = createBlock( { header: { baseFeePerGas: BigInt(10), @@ -98,7 +100,7 @@ console.log(Number(block.header.calcNextBaseFee())) // 11 // So for creating a block with a matching base fee in a certain // chain context you can do: -const blockWithMatchingBaseFee = Block.fromBlockData( +const blockWithMatchingBaseFee = createBlock( { header: { baseFeePerGas: block.header.calcNextBaseFee(), @@ -121,12 +123,13 @@ Starting with the `v4.1.0` release there is support for [EIP-4895](https://eips. ```ts // ./examples/withdrawals.ts -import { Block } from '@ethereumjs/block' -import { Common, Chain } from '@ethereumjs/common' +import { createBlock } from '@ethereumjs/block' +import { Common, Mainnet } from '@ethereumjs/common' import { Address, hexToBytes } from '@ethereumjs/util' + import type { WithdrawalData } from '@ethereumjs/util' -const common = new Common({ chain: Chain.Mainnet }) +const common = new Common({ chain: Mainnet }) const withdrawal = { index: BigInt(0), @@ -135,7 +138,7 @@ const withdrawal = { amount: BigInt(1000), } -const block = Block.fromBlockData( +const block = createBlock( { header: { withdrawalsRoot: hexToBytes( @@ -165,29 +168,29 @@ To create blocks which include blob transactions you have to active EIP-4844 in ```ts // ./examples/4844.ts -import { Common, Chain, Hardfork } from '@ethereumjs/common' -import { Block } from '@ethereumjs/block' -import { BlobEIP4844Transaction } from '@ethereumjs/tx' -import { Address } from '@ethereumjs/util' -import { loadKZG } from 'kzg-wasm' +import { createBlock } from '@ethereumjs/block' +import { Common, Hardfork, Mainnet } from '@ethereumjs/common' +import { create4844BlobTx } from '@ethereumjs/tx' +import { createAddressFromPrivateKey } from '@ethereumjs/util' import { randomBytes } from 'crypto' +import { loadKZG } from 'kzg-wasm' const main = async () => { const kzg = await loadKZG() const common = new Common({ - chain: Chain.Mainnet, + chain: Mainnet, hardfork: Hardfork.Cancun, customCrypto: { kzg, }, }) - const blobTx = BlobEIP4844Transaction.fromTxData( - { blobsData: ['myFirstBlob'], to: Address.fromPrivateKey(randomBytes(32)) }, + const blobTx = create4844BlobTx( + { blobsData: ['myFirstBlob'], to: createAddressFromPrivateKey(randomBytes(32)) }, { common }, ) - const block = Block.fromBlockData( + const block = createBlock( { header: { excessBlobGas: 0n, @@ -207,7 +210,7 @@ const main = async () => { ) } -main() +void main() ``` **Note:** Working with blob transactions needs a manual KZG library installation and global initialization, see [KZG Setup](https://github.com/ethereumjs/ethereumjs-monorepo/tree/master/packages/tx/README.md#kzg-setup) for instructions. @@ -236,8 +239,7 @@ import { const main = async () => { const common = new Common({ chain: Chain.Mainnet, - hardfork: Hardfork.Cancun, - eips: [7685, 4788], + hardfork: Hardfork.Prague, }) const depositRequestData = { @@ -261,7 +263,7 @@ const main = async () => { console.log( `Instantiated block with ${ block.requests?.length - } request, requestTrieValid=${await block.requestsTrieIsValid()}`, + } deposit request, requestTrieValid=${await block.requestsTrieIsValid()}`, ) } @@ -389,15 +391,15 @@ An Ethash/PoW block can be instantiated as follows: ```ts // ./examples/pow.ts -import { Block } from '@ethereumjs/block' -import { Chain, Common, Hardfork } from '@ethereumjs/common' +import { createBlock } from '@ethereumjs/block' +import { Common, Hardfork, Mainnet } from '@ethereumjs/common' -const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Chainstart }) +const common = new Common({ chain: Mainnet, hardfork: Hardfork.Chainstart }) console.log(common.consensusType()) // 'pow' console.log(common.consensusAlgorithm()) // 'ethash' -Block.fromBlockData({}, { common }) +createBlock({}, { common }) console.log(`Old Proof-of-Work block created`) ``` @@ -410,15 +412,15 @@ A clique block can be instantiated as follows: ```ts // ./examples/clique.ts -import { Block } from '@ethereumjs/block' -import { Chain, Common, Hardfork } from '@ethereumjs/common' +import { createBlock } from '@ethereumjs/block' +import { Common, Goerli, Hardfork } from '@ethereumjs/common' -const common = new Common({ chain: Chain.Goerli, hardfork: Hardfork.Chainstart }) +const common = new Common({ chain: Goerli, hardfork: Hardfork.Chainstart }) console.log(common.consensusType()) // 'poa' console.log(common.consensusAlgorithm()) // 'clique' -Block.fromBlockData({ header: { extraData: new Uint8Array(97) } }, { common }) +createBlock({ header: { extraData: new Uint8Array(97) } }, { common }) console.log(`Old Clique Proof-of-Authority block created`) ``` @@ -450,12 +452,12 @@ You can instantiate a Merge/PoS block like this: ```ts // ./examples/pos.ts -import { Block } from '@ethereumjs/block' -import { Chain, Common } from '@ethereumjs/common' +import { createBlock } from '@ethereumjs/block' +import { Common, Mainnet } from '@ethereumjs/common' -const common = new Common({ chain: Chain.Mainnet }) +const common = new Common({ chain: Mainnet }) -const block = Block.fromBlockData( +const block = createBlock( { // Provide your block data here or use default values }, diff --git a/packages/blockchain/README.md b/packages/blockchain/README.md index 1bae18a2b33..37a554bacce 100644 --- a/packages/blockchain/README.md +++ b/packages/blockchain/README.md @@ -38,22 +38,22 @@ The following is an example to instantiate a simple Blockchain object, put block ```ts // ./examples/simple.ts -import { Block } from '@ethereumjs/block' -import { Blockchain } from '@ethereumjs/blockchain' -import { Common, Hardfork } from '@ethereumjs/common' +import { createBlock } from '@ethereumjs/block' +import { createBlockchain } from '@ethereumjs/blockchain' +import { Common, Hardfork, Mainnet } from '@ethereumjs/common' import { bytesToHex } from '@ethereumjs/util' const main = async () => { - const common = new Common({ chain: 'mainnet', hardfork: Hardfork.London }) + const common = new Common({ chain: Mainnet, hardfork: Hardfork.London }) // Use the safe static constructor which awaits the init method - const blockchain = await Blockchain.create({ + const blockchain = await createBlockchain({ validateBlocks: false, // Skipping validation so we can make a simple chain without having to provide complete blocks validateConsensus: false, common, }) // We use minimal data to provide a sequence of blocks (increasing number, difficulty, and then setting parent hash to previous block) - const block = Block.fromBlockData( + const block = createBlock( { header: { number: 1n, @@ -63,7 +63,7 @@ const main = async () => { }, { common, setHardfork: true }, ) - const block2 = Block.fromBlockData( + const block2 = createBlock( { header: { number: 2n, @@ -87,7 +87,7 @@ const main = async () => { // Block 1: 0xa1a061528d74ba81f560e1ebc4f29d6b58171fc13b72b876cdffe6e43b01bdc5 // Block 2: 0x5583be91cf9fb14f5dbeb03ad56e8cef19d1728f267c35a25ba5a355a528f602 } -main() +void main() ``` ### Database Abstraction / Removed LevelDB Dependency @@ -141,16 +141,17 @@ For many custom chains we might come across a genesis configuration, which can b ```ts // ./examples/gethGenesis.ts -import { Blockchain } from '@ethereumjs/blockchain' -import { Common, parseGethGenesis } from '@ethereumjs/common' +import { createBlockchain } from '@ethereumjs/blockchain' +import { createCommonFromGethGenesis } from '@ethereumjs/common' import { bytesToHex, parseGethGenesisState } from '@ethereumjs/util' + import gethGenesisJson from './genesisData/post-merge.json' const main = async () => { // Load geth genesis json file into lets say `gethGenesisJson` - const common = Common.fromGethGenesis(gethGenesisJson, { chain: 'customChain' }) + const common = createCommonFromGethGenesis(gethGenesisJson, { chain: 'customChain' }) const genesisState = parseGethGenesisState(gethGenesisJson) - const blockchain = await Blockchain.create({ + const blockchain = await createBlockchain({ genesisState, common, }) @@ -161,7 +162,7 @@ const main = async () => { ) } -main() +void main() ``` The genesis block from the initialized `Blockchain` can be retrieved via the `Blockchain.genesisBlock` getter. For creating a genesis block from the params in `@ethereumjs/common`, the `createGenesisBlock(stateRoot: Buffer): Block` method can be used. diff --git a/packages/common/README.md b/packages/common/README.md index d0cad1bd892..992ca47d22f 100644 --- a/packages/common/README.md +++ b/packages/common/README.md @@ -291,8 +291,6 @@ use the `chain` option to activate one of the custom chains passed or activate a (e.g. `mainnet`) and switch to other chains - including the custom ones - by using `Common.setChain()`. ```ts -// ./examples/customChains.ts - import { Common } from '@ethereumjs/common' import myCustomChain1 from './genesisData/testnet.json' import myCustomChain2 from './genesisData/testnet2.json' diff --git a/packages/devp2p/README.md b/packages/devp2p/README.md index a9c7269b8dd..bf0a114b396 100644 --- a/packages/devp2p/README.md +++ b/packages/devp2p/README.md @@ -64,7 +64,7 @@ Create your peer table: // examples/dpt.ts import { DPT } from '@ethereumjs/devp2p' -import { bytesToHex, hexToBytes, randomBytes } from '@ethereumjs/util' +import { bytesToHex, hexToBytes } from '@ethereumjs/util' const PRIVATE_KEY = hexToBytes('0xed6df2d4b7e82d105538e4a1279925a16a84e772243e80a561e1b201f2e78220') const main = async () => { @@ -77,10 +77,10 @@ const main = async () => { }) console.log(`DPT is active and has id - ${bytesToHex(dpt.id!)}`) // Should log the DPT's hex ID - 0xcd80bb7a768432302d267729c15da61d172373ea036... - await dpt.destroy() + dpt.destroy() } -main() +void main() ``` Add some bootstrap nodes (or some custom nodes with `dpt.addPeer()`): @@ -165,14 +165,14 @@ instance with the network you want to connect to and then create an `RLPx` objec ```ts // ./examples/rlpx.ts -import { Chain, Common } from '@ethereumjs/common' -import { RLPx, ETH } from '@ethereumjs/devp2p' +import { Common, Mainnet } from '@ethereumjs/common' +import { ETH, RLPx } from '@ethereumjs/devp2p' import { hexToBytes } from '@ethereumjs/util' const main = async () => { - const common = new Common({ chain: Chain.Mainnet }) + const common = new Common({ chain: Mainnet }) const PRIVATE_KEY = hexToBytes( - '0xed6df2d4b7e82d105538e4a1279925a16a84e772243e80a561e1b201f2e78220' + '0xed6df2d4b7e82d105538e4a1279925a16a84e772243e80a561e1b201f2e78220', ) const rlpx = new RLPx(PRIVATE_KEY, { maxPeers: 25, @@ -180,10 +180,10 @@ const main = async () => { common, }) console.log(`RLPx is active - ${rlpx._isAlive()}`) - await rlpx.destroy() + rlpx.destroy() } -main() +void main() ``` ### API @@ -264,8 +264,8 @@ Wait for follow-up messages to arrive, send your responses. eth.events.on('message', async (code: ETH.MESSAGE_CODES, payload: any) => { // We keep track of how many of each message type are received - if (code in ETH.MESSAGE_CODES) { - requests.msgTypes[code] = code + 1 + if (code in requests.msgTypes) { + requests.msgTypes[code]++ ``` See the `peer-communication.ts` example for a more detailed use case. @@ -333,7 +333,7 @@ les.sendStatus({ forkID: [hexToBytes('0x3b8e0691'), intToBytes(1)], }) -les.events.once('status', (status: LES.Status) => { +les.events.once('status', (status: devp2p.LES.Status) => { const msg = [ Uint8Array.from([]), [ @@ -351,7 +351,7 @@ Wait for follow-up messages to arrive, send your responses. ```ts // ./examples/peer-communication-les.ts#L103-L105 -les.events.on('message', async (code: LES.MESSAGE_CODES, payload: any) => { +les.events.on('message', async (code: devp2p.LES.MESSAGE_CODES, payload: any) => { switch (code) { case devp2p.LES.MESSAGE_CODES.BLOCK_HEADERS: { ``` diff --git a/packages/ethash/README.md b/packages/ethash/README.md index 41346153d9e..94b0a6827fb 100644 --- a/packages/ethash/README.md +++ b/packages/ethash/README.md @@ -26,9 +26,11 @@ npm install @ethereumjs/ethash ```ts // ./examples/powBlock.ts +import { createBlockFromRLPSerializedBlock } from '@ethereumjs/block' import { Ethash } from '@ethereumjs/ethash' -import { Block } from '@ethereumjs/block' -import { DBObject, hexToBytes, MapDB } from '@ethereumjs/util' +import { MapDB, hexToBytes } from '@ethereumjs/util' + +import type { DBObject } from '@ethereumjs/util' const cacheDB = new MapDB() @@ -36,7 +38,7 @@ const ethash = new Ethash(cacheDB) const validblockRlp = '0xf90667f905fba0a8d5b7a4793baaede98b5236954f634a0051842df6a252f6a80492fd888678bda01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0f93c8db1e931daa2e22e39b5d2da6fb4074e3d544094857608536155e3521bc1a0bb7495628f9160ddbcf6354380ee32c300d594e833caec3a428041a66e7bade1a0c7778a7376099ee2e5c455791c1885b5c361b95713fddcbe32d97fd01334d296b90100000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000400000000000000000000000000000000000000000000000000000008302000001832fefd882560b84559c17b9b9040001020304050607080910111213141516171819202122232410000000000000000000200000000000000000003000000000000000000040000000000000000000500000000000000000006000000000000000000070000000000000000000800000000000000000009000000000000000000010000000000000000000100000000000000000002000000000000000000030000000000000000000400000000000000000005000000000000000000060000000000000000000700000000000000000008000000000000000000090000000000000000000100000000000000000001000000000000000000020000000000000000000300000000000000000004000000000000000000050000000000000000000600000000000000000007000000000000000000080000000000000000000900000000000000000001000000000000000000010000000000000000000200000000000000000003000000000000000000040000000000000000000500000000000000000006000000000000000000070000000000000000000800000000000000000009000000000000000000010000000000000000000100000000000000000002000000000000000000030000000000000000000400000000000000000005000000000000000000060000000000000000000700000000000000000008000000000000000000090000000000000000000100000000000000000001000000000000000000020000000000000000000300000000000000000004000000000000000000050000000000000000000600000000000000000007000000000000000000080000000000000000000900000000000000000001000000000000000000010000000000000000000200000000000000000003000000000000000000040000000000000000000500000000000000000006000000000000000000070000000000000000000800000000000000000009000000000000000000010000000000000000000100000000000000000002000000000000000000030000000000000000000400000000000000000005000000000000000000060000000000000000000700000000000000000008000000000000000000090000000000000000000100000000000000000001000000000000000000020000000000000000000300000000000000000004000000000000000000050000000000000000000600000000000000000007000000000000000000080000000000000000000900000000000000000001000000000000000000010000000000000000000200000000000000000003000000000000000000040000000000000000000500000000000000000006000000000000000000070000000000000000000800000000000000000009000000000000000000010000000000000000000a09c7b47112a3afb385c12924bf6280d273c106eea7caeaf5131d8776f61056c148876ae05d46b58d1fff866f864800a82c35094095e7baea6a6c7c4c2dfeb977efac326af552d8785012a05f200801ba01d2c92cfaeb04e53acdff2b5d42005ff6aacdb0105e64eb8c30c273f445d2782a01e7d50ffce57840360c57d94977b8cdebde614da23e8d1e77dc07928763cfe21c0' -const validBlock = Block.fromRLPSerializedBlock(hexToBytes(validblockRlp), { +const validBlock = createBlockFromRLPSerializedBlock(hexToBytes(validblockRlp), { setHardfork: true, skipConsensusFormatValidation: true, }) @@ -54,18 +56,20 @@ See the following example on how to use the new `Miner` class: ```ts // ./examples/miner.ts -import { Block } from '@ethereumjs/block' +import { createBlock } from '@ethereumjs/block' import { Ethash } from '@ethereumjs/ethash' -import { DBObject, MapDB, bytesToHex } from '@ethereumjs/util' +import { MapDB, bytesToHex } from '@ethereumjs/util' + +import type { DBObject } from '@ethereumjs/util' -const block = Block.fromBlockData( +const block = createBlock( { header: { difficulty: BigInt(100), number: BigInt(1), }, }, - { setHardfork: true, skipConsensusFormatValidation: true } + { setHardfork: true, skipConsensusFormatValidation: true }, ) const cacheDB = new MapDB() diff --git a/packages/evm/README.md b/packages/evm/README.md index 3045606161f..25a19e0dec7 100644 --- a/packages/evm/README.md +++ b/packages/evm/README.md @@ -32,16 +32,16 @@ The following is the simplest example for an EVM instantiation: ```ts // ./examples/simple.ts +import { createEVM } from '@ethereumjs/evm' import { hexToBytes } from '@ethereumjs/util' -import { EVM } from '@ethereumjs/evm' const main = async () => { - const evm = await EVM.create() + const evm = await createEVM() const res = await evm.runCode({ code: hexToBytes('0x6001') }) // PUSH1 01 -- simple bytecode to push 1 onto the stack console.log(res.executionGasUsed) // 3n } -main() +void main() ``` Note: with the switch from v2 to v3 the old direct `new EVM()` constructor usage has been deprecated and an `EVM` now has to be instantiated with the async static `EVM.create()` constructor. @@ -53,18 +53,20 @@ If the EVM should run on a certain state an `@ethereumjs/statemanager` is needed ```ts // ./examples/withBlockchain.ts -import { Blockchain } from '@ethereumjs/blockchain' -import { Chain, Common, Hardfork } from '@ethereumjs/common' -import { EVM } from '@ethereumjs/evm' +import { createBlockchain } from '@ethereumjs/blockchain' +import { Common, Hardfork, Mainnet } from '@ethereumjs/common' +import { createEVM } from '@ethereumjs/evm' import { DefaultStateManager } from '@ethereumjs/statemanager' -import { bytesToHex } from '@ethereumjs/util' +import { bytesToHex, hexToBytes } from '@ethereumjs/util' + +import type { PrefixedHexString } from '@ethereumjs/util' const main = async () => { - const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Shanghai }) + const common = new Common({ chain: Mainnet, hardfork: Hardfork.Shanghai }) const stateManager = new DefaultStateManager() - const blockchain = await Blockchain.create() + const blockchain = await createBlockchain() - const evm = await EVM.create({ + const evm = await createEVM({ common, stateManager, blockchain, @@ -83,7 +85,7 @@ const main = async () => { }) const results = await evm.runCode({ - code: Buffer.from(code.join(''), 'hex'), + code: hexToBytes(('0x' + code.join('')) as PrefixedHexString), gasLimit: BigInt(0xffff), }) @@ -132,7 +134,7 @@ const main = async () => { console.log(`Precompile result:${bytesToHex(result.returnValue)}`) } -main() +void main() ``` ### EIP-2537 BLS Precompiles (Prague) @@ -255,16 +257,16 @@ If you want to activate an EIP not currently active on the hardfork your `common ```ts // ./examples/eips.ts -import { Chain, Common } from '@ethereumjs/common' -import { EVM } from '@ethereumjs/evm' +import { Common, Mainnet } from '@ethereumjs/common' +import { createEVM } from '@ethereumjs/evm' const main = async () => { - const common = new Common({ chain: Chain.Mainnet, eips: [3074] }) - const evm = await EVM.create({ common }) - console.log(`EIP 3074 is active - ${evm.common.isActivatedEIP(3074)}`) + const common = new Common({ chain: Mainnet, eips: [7702] }) + const evm = await createEVM({ common }) + console.log(`EIP 7702 is active - ${evm.common.isActivatedEIP(7702)}`) } -main() +void main() ``` Currently supported EIPs: @@ -320,9 +322,9 @@ To run EVM related EIP-4844 functionality you have to active the EIP in the asso ```ts // ./examples/4844.ts -import { Common, Chain, Hardfork } from '@ethereumjs/common' +import { Common, Hardfork, Mainnet } from '@ethereumjs/common' -const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Shanghai, eips: [4844] }) +const common = new Common({ chain: Mainnet, hardfork: Hardfork.Shanghai, eips: [4844] }) ``` EIP-4844 comes with a new opcode `BLOBHASH` (Attention! Renamed from `DATAHASH`) and adds a new point evaluation precompile at address `0x0a` diff --git a/packages/genesis/README.md b/packages/genesis/README.md index f030dd290a2..4ad4845abaa 100644 --- a/packages/genesis/README.md +++ b/packages/genesis/README.md @@ -27,14 +27,14 @@ npm i @ethereumjs/genesis ```ts // ./examples/simple.ts -import { getGenesis } from '@ethereumjs/genesis' import { Chain } from '@ethereumjs/common' // or directly use chain ID +import { getGenesis } from '@ethereumjs/genesis' const mainnetGenesis = getGenesis(Chain.Mainnet) console.log( `This balance for account 0x000d836201318ec6899a67540690382780743280 in this chain's genesis state is ${parseInt( - mainnetGenesis!['0x000d836201318ec6899a67540690382780743280'] as string - )}` + mainnetGenesis!['0x000d836201318ec6899a67540690382780743280'] as string, + )}`, ) ``` diff --git a/packages/rlp/README.md b/packages/rlp/README.md index 9532de06b6f..7b2c8dbcf92 100644 --- a/packages/rlp/README.md +++ b/packages/rlp/README.md @@ -24,8 +24,8 @@ Install with `-g` if you want to use the CLI. ```ts // ./examples/simple.ts -import assert from 'assert' import { RLP } from '@ethereumjs/rlp' +import assert from 'assert' const nestedList = [[], [[]], [[], [[]]]] const encoded = RLP.encode(nestedList) diff --git a/packages/statemanager/README.md b/packages/statemanager/README.md index 85e194be109..faac17e544e 100644 --- a/packages/statemanager/README.md +++ b/packages/statemanager/README.md @@ -39,9 +39,8 @@ It also includes a checkpoint/revert/commit mechanism to either persist or rever ```ts // ./examples/basicUsage.ts -import { Account, Address } from '@ethereumjs/util' import { DefaultStateManager } from '@ethereumjs/statemanager' -import { hexToBytes } from '@ethereumjs/util' +import { Account, Address, hexToBytes } from '@ethereumjs/util' const main = async () => { const stateManager = new DefaultStateManager() @@ -56,10 +55,10 @@ const main = async () => { console.log( `Account at address ${address.toString()} has balance ${ (await stateManager.getAccount(address))?.balance - }` + }`, ) } -main() +void main() ``` #### Account, Storage and Code Caches @@ -81,18 +80,19 @@ This state manager can be instantiated and used as follows: ```ts // ./examples/simple.ts +import { Account, createAddressFromPrivateKey, randomBytes } from '@ethereumjs/util' + import { SimpleStateManager } from '../src/index.js' -import { Account, Address, randomBytes } from '@ethereumjs/util' const main = async () => { const sm = new SimpleStateManager() - const address = Address.fromPrivateKey(randomBytes(32)) + const address = createAddressFromPrivateKey(randomBytes(32)) const account = new Account(0n, 0xfffffn) await sm.putAccount(address, account) console.log(await sm.getAccount(address)) } -main() +void main() ``` ### `DefaultStateManager` -> Proofs @@ -106,9 +106,8 @@ See below example for common usage: ```ts // ./examples/fromProofInstantiation.ts -import { Address } from '@ethereumjs/util' import { DefaultStateManager } from '@ethereumjs/statemanager' -import { hexToBytes } from '@ethereumjs/util' +import { Address, hexToBytes } from '@ethereumjs/util' const main = async () => { // setup `stateManager` with some existing address @@ -116,17 +115,17 @@ const main = async () => { const contractAddress = new Address(hexToBytes('0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b')) const byteCode = hexToBytes('0x67ffffffffffffffff600160006000fb') const storageKey1 = hexToBytes( - '0x0000000000000000000000000000000000000000000000000000000000000001' + '0x0000000000000000000000000000000000000000000000000000000000000001', ) const storageKey2 = hexToBytes( - '0x0000000000000000000000000000000000000000000000000000000000000002' + '0x0000000000000000000000000000000000000000000000000000000000000002', ) const storageValue1 = hexToBytes('0x01') const storageValue2 = hexToBytes('0x02') - await stateManager.putContractCode(contractAddress, byteCode) - await stateManager.putContractStorage(contractAddress, storageKey1, storageValue1) - await stateManager.putContractStorage(contractAddress, storageKey2, storageValue2) + await stateManager.putCode(contractAddress, byteCode) + await stateManager.putStorage(contractAddress, storageKey1, storageValue1) + await stateManager.putStorage(contractAddress, storageKey2, storageValue2) const proof = await stateManager.getProof(contractAddress) const proofWithStorage = await stateManager.getProof(contractAddress, [storageKey1, storageKey2]) @@ -134,26 +133,20 @@ const main = async () => { // To add more proof data, use `addProofData` await partialStateManager.addProofData(proofWithStorage) - console.log(await partialStateManager.getContractCode(contractAddress)) // contract bytecode is not included in proof - console.log( - await partialStateManager.getContractStorage(contractAddress, storageKey1), - storageValue1 - ) // should match - console.log( - await partialStateManager.getContractStorage(contractAddress, storageKey2), - storageValue2 - ) // should match + console.log(await partialStateManager.getCode(contractAddress)) // contract bytecode is not included in proof + console.log(await partialStateManager.getStorage(contractAddress, storageKey1), storageValue1) // should match + console.log(await partialStateManager.getStorage(contractAddress, storageKey2), storageValue2) // should match const accountFromNewSM = await partialStateManager.getAccount(contractAddress) const accountFromOldSM = await stateManager.getAccount(contractAddress) console.log(accountFromNewSM, accountFromOldSM) // should match - const slot1FromNewSM = await stateManager.getContractStorage(contractAddress, storageKey1) - const slot2FromNewSM = await stateManager.getContractStorage(contractAddress, storageKey2) + const slot1FromNewSM = await stateManager.getStorage(contractAddress, storageKey1) + const slot2FromNewSM = await stateManager.getStorage(contractAddress, storageKey2) console.log(slot1FromNewSM, storageValue1) // should match console.log(slot2FromNewSM, storageValue2) // should match } -main() +void main() ``` ### `RPCStateManager` @@ -165,21 +158,21 @@ A simple example of usage: ```ts // ./examples/rpcStateManager.ts -import { Address } from '@ethereumjs/util' import { RPCStateManager } from '@ethereumjs/statemanager' +import { createAddressFromString } from '@ethereumjs/util' const main = async () => { try { const provider = 'https://path.to.my.provider.com' const stateManager = new RPCStateManager({ provider, blockTag: 500000n }) - const vitalikDotEth = Address.fromString('0xd8da6bf26964af9d7eed9e03e53415d37aa96045') + const vitalikDotEth = createAddressFromString('0xd8da6bf26964af9d7eed9e03e53415d37aa96045') const account = await stateManager.getAccount(vitalikDotEth) console.log('Vitalik has a current ETH balance of ', account?.balance) } catch (e) { console.log(e.message) // fetch fails because provider url is not real. please replace provider with a valid rpc url string. } } -main() +void main() ``` **Note:** Usage of this StateManager can cause a heavy load regarding state request API calls, so be careful (or at least: aware) if used in combination with a JSON-RPC provider connecting to a third-party API service like Infura! @@ -193,8 +186,8 @@ In order to have an EVM instance that supports the BLOCKHASH opcode (which requi ```ts // ./examples/evm.ts -import { RPCStateManager, RPCBlockChain } from '@ethereumjs/statemanager' -import { EVM } from '@ethereumjs/evm' +import { createEVM } from '@ethereumjs/evm' +import { RPCBlockChain, RPCStateManager } from '@ethereumjs/statemanager' const main = async () => { try { @@ -202,12 +195,12 @@ const main = async () => { const blockchain = new RPCBlockChain(provider) const blockTag = 1n const state = new RPCStateManager({ provider, blockTag }) - const evm = await EVM.create({ blockchain, stateManager: state }) // note that evm is ready to run BLOCKHASH opcodes (over RPC) + const evm = await createEVM({ blockchain, stateManager: state }) // note that evm is ready to run BLOCKHASH opcodes (over RPC) } catch (e) { console.log(e.message) // fetch would fail because provider url is not real. please replace provider with a valid rpc url string. } } -main() +void main() ``` Note: Failing to provide the `RPCBlockChain` instance when instantiating the EVM means that the `BLOCKHASH` opcode will fail to work correctly during EVM execution. diff --git a/packages/trie/README.md b/packages/trie/README.md index d77b074c92d..a16399d1cbd 100644 --- a/packages/trie/README.md +++ b/packages/trie/README.md @@ -32,17 +32,17 @@ It is best to select the variant that is most appropriate for your unique use ca ```ts // ./examples/basicUsage.ts -import { Trie } from '@ethereumjs/trie' -import { bytesToUtf8, MapDB, utf8ToBytes } from '@ethereumjs/util' +import { createTrie } from '@ethereumjs/trie' +import { MapDB, bytesToUtf8, utf8ToBytes } from '@ethereumjs/util' async function test() { - const trie = await Trie.create({ db: new MapDB() }) + const trie = await createTrie({ db: new MapDB() }) await trie.put(utf8ToBytes('test'), utf8ToBytes('one')) const value = await trie.get(utf8ToBytes('test')) console.log(value ? bytesToUtf8(value) : 'not found') // 'one' } -test() +void test() ``` ### WASM Crypto Support @@ -56,17 +56,17 @@ This library by default uses JavaScript implementations for the basic standard c ```ts // ./examples/basicUsage.ts -import { Trie } from '@ethereumjs/trie' -import { bytesToUtf8, MapDB, utf8ToBytes } from '@ethereumjs/util' +import { createTrie } from '@ethereumjs/trie' +import { MapDB, bytesToUtf8, utf8ToBytes } from '@ethereumjs/util' async function test() { - const trie = await Trie.create({ db: new MapDB() }) + const trie = await createTrie({ db: new MapDB() }) await trie.put(utf8ToBytes('test'), utf8ToBytes('one')) const value = await trie.get(utf8ToBytes('test')) console.log(value ? bytesToUtf8(value) : 'not found') // 'one' } -test() +void test() ``` When the static `Trie.create` constructor is used without any options, the `trie` object is instantiated with defaults configured to match the Ethereum production spec (i.e. keys are hashed using SHA256). It also persists the state root of the tree on each write operation, ensuring that your trie remains in the state you left it when you start your application the next time. @@ -80,9 +80,13 @@ The following is an example for using the `Trie.createFromProof()` static constr ```ts // ./examples/createFromProof.ts -import { Trie } from '@ethereumjs/trie' -import { bytesToUtf8 } from '@ethereumjs/util' -import { utf8ToBytes } from 'ethereum-cryptography/utils' +import { + Trie, + createMerkleProof, + createTrieFromProof, + updateTrieFromMerkleProof, +} from '@ethereumjs/trie' +import { bytesToUtf8, utf8ToBytes } from '@ethereumjs/util' async function main() { const k1 = utf8ToBytes('keyOne') @@ -92,12 +96,12 @@ async function main() { await someOtherTrie.put(k1, utf8ToBytes('valueOne')) await someOtherTrie.put(k2, utf8ToBytes('valueTwo')) - const proof = await someOtherTrie.createProof(k1) - const trie = await Trie.createFromProof(proof, { useKeyHashing: true }) - const otherProof = await someOtherTrie.createProof(k2) + const proof = await createMerkleProof(someOtherTrie, k1) + const trie = await createTrieFromProof(proof, { useKeyHashing: true }) + const otherProof = await createMerkleProof(someOtherTrie, k2) - // To add more proofs to the trie, use `updateFromProof` - await trie.updateFromProof(otherProof) + // To add more proofs to the trie, use `updateTrieFromMerkleProof` + await updateTrieFromMerkleProof(trie, otherProof) const value = await trie.get(k1) console.log(bytesToUtf8(value!)) // valueOne @@ -105,7 +109,7 @@ async function main() { console.log(bytesToUtf8(otherValue!)) // valueTwo } -main() +void main() ``` For further proof usage documentation see additional documentation section below. @@ -119,11 +123,11 @@ The new walk functionality can be used like the following: ```ts // ./examples/trieWalking.ts -import { Trie } from '@ethereumjs/trie' -import { utf8ToBytes } from 'ethereum-cryptography/utils' +import { createTrie } from '@ethereumjs/trie' +import { utf8ToBytes } from '@ethereumjs/util' async function main() { - const trie = await Trie.create() + const trie = await createTrie() await trie.put(utf8ToBytes('key'), utf8ToBytes('val')) const walk = trie.walkTrieIterable(trie.root()) @@ -132,7 +136,7 @@ async function main() { console.log({ node, currentKey }) } } -main() +void main() ``` ### `Trie` Configuration Options @@ -152,11 +156,11 @@ As an example, to leverage `LevelDB` for all operations then you should create a ```ts // ./examples/customLevelDB.ts#L127-L131 -async function main() { const trie = new Trie({ db: new LevelDB(new Level('MY_TRIE_DB_LOCATION') as any) }) - console.log(await trie.database().db) // LevelDB { ... + console.log(trie.database().db) // LevelDB { ... } -main() +void main() + ``` #### Node Deletion (Pruning) @@ -170,18 +174,18 @@ You can enable persistence by setting the `useRootPersistence` option to `true` ```ts // ./examples/rootPersistence.ts -import { Trie } from '@ethereumjs/trie' +import { createTrie } from '@ethereumjs/trie' import { bytesToHex } from '@ethereumjs/util' async function main() { - const trie = await Trie.create({ + const trie = await createTrie({ useRootPersistence: true, }) // this logs the empty root value that has been persisted to the trie db console.log(bytesToHex(trie.root())) // 0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421 } -main() +void main() ``` ## Proofs @@ -199,8 +203,8 @@ The following code demonstrates how to construct and subsequently verify a proof // proof-of-inclusion await trie.put(k1, v1) -let proof = await trie.createProof(k1) -let value = await trie.verifyProof(trie.root(), k1, proof) +let proof = await createMerkleProof(trie, k1) +let value = await verifyMerkleProof(trie, trie.root(), k1, proof) console.log(value ? bytesToUtf8(value) : 'not found') // 'one' ``` @@ -214,8 +218,8 @@ The following code demonstrates how to construct and subsequently verify a proof // proof-of-exclusion await trie.put(k1, v1) await trie.put(k2, v2) -proof = await trie.createProof(utf8ToBytes('key3')) -value = await trie.verifyProof(trie.root(), utf8ToBytes('key3'), proof) +proof = await createMerkleProof(trie, utf8ToBytes('key3')) +value = await verifyMerkleProof(trie, trie.root(), utf8ToBytes('key3'), proof) console.log(value ? bytesToUtf8(value) : 'null') // null ``` @@ -229,10 +233,10 @@ If `verifyProof` detects an invalid proof, it will throw an error. While contriv // invalid proof await trie.put(k1, v1) await trie.put(k2, v2) -proof = await trie.createProof(k2) +proof = await createMerkleProof(trie, k2) proof[0].reverse() try { - const value = await trie.verifyProof(trie.root(), k2, proof) // results in error + const _value = await verifyMerkleProof(trie, trie.root(), k2, proof) // results in error } catch (err) { console.log(err) } diff --git a/packages/tx/README.md b/packages/tx/README.md index 8d683e61992..c0aaaf6b955 100644 --- a/packages/tx/README.md +++ b/packages/tx/README.md @@ -40,15 +40,15 @@ Initialization can then be done like the following: ```ts // ./examples/initKzg.ts +import { Common, Hardfork, Mainnet } from '@ethereumjs/common' import { loadKZG } from 'kzg-wasm' -import { Chain, Common, Hardfork } from '@ethereumjs/common' const main = async () => { const kzg = await loadKZG() // Instantiate `common` const common = new Common({ - chain: Chain.Mainnet, + chain: Mainnet, hardfork: Hardfork.Cancun, customCrypto: { kzg }, }) @@ -56,7 +56,7 @@ const main = async () => { console.log(common.customCrypto.kzg) // should output the KZG API as an object } -main() +void main() ``` Note: Manual addition is necessary because we did not want to bundle our libraries with WASM code by default, since some projects are then prevented from using our libraries. @@ -124,8 +124,8 @@ See the following code snipped for an example on how to instantiate (using the ` ```ts // ./examples/blobTx.ts -import { Chain, Common, Hardfork } from '@ethereumjs/common' -import { BlobEIP4844Transaction } from '@ethereumjs/tx' +import { Common, Hardfork, Mainnet } from '@ethereumjs/common' +import { create4844BlobTx } from '@ethereumjs/tx' import { bytesToHex } from '@ethereumjs/util' import { loadKZG } from 'kzg-wasm' @@ -133,7 +133,7 @@ const main = async () => { const kzg = await loadKZG() const common = new Common({ - chain: Chain.Mainnet, + chain: Mainnet, hardfork: Hardfork.Shanghai, eips: [4844], customCrypto: { kzg }, @@ -157,12 +157,12 @@ const main = async () => { blobsData: ['abcd'], } - const tx = BlobEIP4844Transaction.fromTxData(txData, { common }) + const tx = create4844BlobTx(txData, { common }) console.log(bytesToHex(tx.hash())) //0x3c3e7c5e09c250d2200bcc3530f4a9088d7e3fb4ea3f4fccfd09f535a3539e84 } -main() +void main() ``` Note that `versionedHashes` and `kzgCommitments` have a real length of 32 bytes, `blobs` have a real length of `4096` bytes and values are trimmed here for brevity. @@ -182,11 +182,11 @@ This is the recommended tx type starting with the activation of the `london` HF, ```ts // ./examples/londonTx.ts -import { Chain, Common, Hardfork } from '@ethereumjs/common' -import { FeeMarketEIP1559Transaction } from '@ethereumjs/tx' +import { Common, Hardfork, Mainnet } from '@ethereumjs/common' +import { create1559FeeMarketTx } from '@ethereumjs/tx' import { bytesToHex } from '@ethereumjs/util' -const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.London }) +const common = new Common({ chain: Mainnet, hardfork: Hardfork.London }) const txData = { data: '0x1a8451e600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', @@ -204,7 +204,7 @@ const txData = { type: '0x02', } -const tx = FeeMarketEIP1559Transaction.fromTxData(txData, { common }) +const tx = create1559FeeMarketTx(txData, { common }) console.log(bytesToHex(tx.hash())) // 0x6f9ef69ccb1de1aea64e511efd6542541008ced321887937c95b03779358ec8a ``` @@ -232,7 +232,7 @@ const tx = EOACodeEIP7702Transaction.fromTxData( { authorizationList: [ { - chainId: '0x1', + chainId: '0x2', address: `0x${'20'.repeat(20)}`, nonce: ['0x1'], yParity: '0x1', @@ -262,11 +262,11 @@ This transaction type has been introduced along the `berlin` HF. See the followi ```ts // ./examples/accessListTx.ts -import { Chain, Common, Hardfork } from '@ethereumjs/common' -import { AccessListEIP2930Transaction } from '@ethereumjs/tx' +import { Common, Hardfork, Mainnet } from '@ethereumjs/common' +import { create2930AccessListTx } from '@ethereumjs/tx' import { bytesToHex } from '@ethereumjs/util' -const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Berlin }) +const common = new Common({ chain: Mainnet, hardfork: Hardfork.Berlin }) const txData = { data: '0x1a8451e600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', @@ -291,7 +291,7 @@ const txData = { type: '0x01', } -const tx = AccessListEIP2930Transaction.fromTxData(txData, { common }) +const tx = create2930AccessListTx(txData, { common }) console.log(bytesToHex(tx.hash())) // 0x9150cdebad74e88b038e6c6b964d99af705f9c0883d7f0bbc0f3e072358f5b1d ``` @@ -310,12 +310,13 @@ See this [example script](./examples/transactions.ts) or the following code exam ```ts // ./examples/legacyTx.ts -import { Chain, Common, Hardfork } from '@ethereumjs/common' -import { LegacyTransaction } from '@ethereumjs/tx' +import { Common, Hardfork, Mainnet } from '@ethereumjs/common' +import { createLegacyTx } from '@ethereumjs/tx' import { bytesToHex } from '@ethereumjs/util' +import { hexToBytes } from 'ethereum-cryptography/utils' const txParams = { - nonce: '0x00', + nonce: '0x0', gasPrice: '0x09184e72a000', gasLimit: '0x2710', to: '0x0000000000000000000000000000000000000000', @@ -323,17 +324,14 @@ const txParams = { data: '0x7f7465737432000000000000000000000000000000000000000000000000000000600057', } -const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Istanbul }) -const tx = LegacyTransaction.fromTxData(txParams, { common }) +const common = new Common({ chain: Mainnet, hardfork: Hardfork.Istanbul }) +const tx = createLegacyTx(txParams, { common }) -const privateKey = Buffer.from( - 'e331b6d69882b4cb4ea581d88e0b604039a3de5967688d3dcffdd2270c0fd109', - 'hex', -) +const privateKey = hexToBytes('0xe331b6d69882b4cb4ea581d88e0b604039a3de5967688d3dcffdd2270c0fd109') const signedTx = tx.sign(privateKey) -const serializedTx = signedTx.serialize() +const _serializedTx = signedTx.serialize() console.log(bytesToHex(signedTx.hash())) // 0x894b72d87f8333fccd29d1b3aca39af69d97a6bc281e7e7a3a60640690a3cd2b ``` @@ -344,13 +342,15 @@ If you only know on runtime which tx type will be used within your code or if yo ```ts // ./examples/txFactory.ts -import { Chain, Common, Hardfork } from '@ethereumjs/common' -import { Capability, EIP1559CompatibleTx, TransactionFactory } from '@ethereumjs/tx' +import { Common, Hardfork, Mainnet } from '@ethereumjs/common' +import { Capability, createTxFromTxData } from '@ethereumjs/tx' + +import type { EIP1559CompatibleTx } from '@ethereumjs/tx' -const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.London }) +const common = new Common({ chain: Mainnet, hardfork: Hardfork.London }) const txData = { type: 2, maxFeePerGas: BigInt(20) } // Creates an EIP-1559 compatible transac -const tx = TransactionFactory.fromTxData(txData, { common }) +const tx = createTxFromTxData(txData, { common }) if (tx.supports(Capability.EIP1559FeeMarket)) { console.log( @@ -377,13 +377,14 @@ This library has been tested to work with various L2 networks (`v3.3.0`+). All p ```ts // ./examples/l2tx.ts -import { Common, CustomChain } from '@ethereumjs/common' -import { LegacyTransaction } from '@ethereumjs/tx' -import { Address, bytesToHex, hexToBytes } from '@ethereumjs/util' +import { Mainnet, createCustomCommon } from '@ethereumjs/common' +import { createLegacyTx } from '@ethereumjs/tx' +import { bytesToHex, createAddressFromString, hexToBytes } from '@ethereumjs/util' const pk = hexToBytes('0x076247989df60a82f6e86e58104368676096f84e60972282ee00d4673a2bc9b9') -const to = Address.fromString('0x256e8f0ba532ad83a0debde7501669511a41a1f3') -const common = Common.custom(CustomChain.xDaiChain) +// xDai chain ID +const common = createCustomCommon({ chainId: 100 }, Mainnet) +const to = createAddressFromString('0x256e8f0ba532ad83a0debde7501669511a41a1f3') const txData = { nonce: 0, @@ -393,7 +394,7 @@ const txData = { value: 1, } -const tx = LegacyTransaction.fromTxData(txData, { common }) +const tx = createLegacyTx(txData, { common }) const signedTx = tx.sign(pk) console.log(bytesToHex(signedTx.hash())) // 0xbf98f6f8700812ed6f2314275070256e11945fa48afd80fb301265f6a41a2dc2 ``` diff --git a/packages/util/README.md b/packages/util/README.md index 467aa8341d7..ebd25c96573 100644 --- a/packages/util/README.md +++ b/packages/util/README.md @@ -34,9 +34,9 @@ Class representing an `Account` and providing private/public key and address-rel ```ts // ./examples/account.ts -import { Account } from '@ethereumjs/util' +import { createAccount } from '@ethereumjs/util' -const account = Account.fromAccountData({ +const account = createAccount({ nonce: '0x02', balance: '0x0384', storageRoot: '0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421', @@ -66,9 +66,9 @@ Class representing an Ethereum `Address` with instantiation helpers and validati ```ts // ./examples/address.ts -import { Address } from '@ethereumjs/util' +import { createAddressFromString } from '@ethereumjs/util' -const address = Address.fromString('0x2f015c60e0be116b1f0cd534704db9c92118fb6a') +const address = createAddressFromString('0x2f015c60e0be116b1f0cd534704db9c92118fb6a') console.log(`Ethereum address ${address.toString()} created`) ``` diff --git a/packages/vm/README.md b/packages/vm/README.md index 7cca9d89b30..d328e5cf066 100644 --- a/packages/vm/README.md +++ b/packages/vm/README.md @@ -35,29 +35,29 @@ npm install @ethereumjs/vm ```ts // ./examples/runTx.ts -import { Address } from '@ethereumjs/util' -import { Chain, Common, Hardfork } from '@ethereumjs/common' -import { LegacyTransaction } from '@ethereumjs/tx' -import { VM } from '@ethereumjs/vm' +import { Common, Hardfork, Mainnet } from '@ethereumjs/common' +import { createLegacyTx } from '@ethereumjs/tx' +import { createZeroAddress } from '@ethereumjs/util' +import { VM, runTx } from '@ethereumjs/vm' const main = async () => { - const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Shanghai }) + const common = new Common({ chain: Mainnet, hardfork: Hardfork.Shanghai }) const vm = await VM.create({ common }) - const tx = LegacyTransaction.fromTxData({ + const tx = createLegacyTx({ gasLimit: BigInt(21000), gasPrice: BigInt(1000000000), value: BigInt(1), - to: Address.zero(), + to: createZeroAddress(), v: BigInt(37), r: BigInt('62886504200765677832366398998081608852310526822767264927793100349258111544447'), s: BigInt('21948396863567062449199529794141973192314514851405455194940751428901681436138'), }) - const res = await vm.runTx({ tx, skipBalance: true }) + const res = await runTx(vm, { tx, skipBalance: true }) console.log(res.totalGasSpent) // 21000n - gas cost for simple ETH transfer } -main() +void main() ``` Additionally to the `VM.runTx()` method there is an API method `VM.runBlock()` which allows to run the whole block and execute all included transactions along. @@ -73,24 +73,24 @@ The following non-complete example gives some illustration on how to use the Blo ```ts // ./examples/buildBlock.ts -import { Block } from '@ethereumjs/block' -import { Chain, Common, Hardfork } from '@ethereumjs/common' -import { LegacyTransaction } from '@ethereumjs/tx' -import { Account, Address, bytesToHex, hexToBytes, randomBytes } from '@ethereumjs/util' -import { VM } from '@ethereumjs/vm' +import { createBlock } from '@ethereumjs/block' +import { Common, Mainnet } from '@ethereumjs/common' +import { createLegacyTx } from '@ethereumjs/tx' +import { Account, bytesToHex, createAddressFromPrivateKey, hexToBytes } from '@ethereumjs/util' +import { VM, buildBlock } from '@ethereumjs/vm' const main = async () => { - const common = new Common({ chain: Chain.Mainnet }) + const common = new Common({ chain: Mainnet }) const vm = await VM.create({ common }) - const parentBlock = Block.fromBlockData( + const parentBlock = createBlock( { header: { number: 1n } }, { skipConsensusFormatValidation: true }, ) const headerData = { number: 2n, } - const blockBuilder = await vm.buildBlock({ + const blockBuilder = await buildBlock(vm, { parentBlock, // the parent @ethereumjs/block Block headerData, // header values for the new block blockOpts: { @@ -102,10 +102,10 @@ const main = async () => { }) const pk = hexToBytes('0x26f81cbcffd3d23eace0bb4eac5274bb2f576d310ee85318b5428bf9a71fc89a') - const address = Address.fromPrivateKey(pk) + const address = createAddressFromPrivateKey(pk) const account = new Account(0n, 0xfffffffffn) await vm.stateManager.putAccount(address, account) // create a sending account and give it a big balance - const tx = LegacyTransaction.fromTxData({ gasLimit: 0xffffff, gasPrice: 75n }).sign(pk) + const tx = createLegacyTx({ gasLimit: 0xffffff, gasPrice: 75n }).sign(pk) await blockBuilder.addTransaction(tx) // Add more transactions @@ -114,7 +114,7 @@ const main = async () => { console.log(`Built a block with hash ${bytesToHex(block.hash())}`) } -main() +void main() ``` ### WASM Crypto Support @@ -212,22 +212,25 @@ The following is a simple example for a block run on `Goerli`: ```ts // ./examples/runGoerliBlock.ts -import { Block } from '@ethereumjs/block' -import { Chain, Common } from '@ethereumjs/common' -import { bytesToHex, hexToBytes } from '@ethereumjs/util' +import { createBlockFromRPC } from '@ethereumjs/block' +import { Common, Goerli } from '@ethereumjs/common' +import { bytesToHex } from '@ethereumjs/util' + +import { runBlock } from '../src/index.js' import { VM } from '../src/vm.js' + import goerliBlock2 from './testData/goerliBlock2.json' const main = async () => { - const common = new Common({ chain: Chain.Goerli, hardfork: 'london' }) + const common = new Common({ chain: Goerli, hardfork: 'london' }) const vm = await VM.create({ common, setHardfork: true }) - const block = Block.fromRPC(goerliBlock2, undefined, { common }) - const result = await vm.runBlock({ block, generate: true, skipHeaderValidation: true }) // we skip header validaiton since we are running a block without the full Ethereum history available + const block = createBlockFromRPC(goerliBlock2, undefined, { common }) + const result = await runBlock(vm, { block, generate: true, skipHeaderValidation: true }) // we skip header validaiton since we are running a block without the full Ethereum history available console.log(`The state root for Goerli block 2 is ${bytesToHex(result.stateRoot)}`) } -main() +void main() ``` ### Hardfork Support @@ -239,13 +242,13 @@ An explicit HF in the `VM` - which is then passed on to the inner `EVM` - can be ```ts // ./examples/runTx.ts#L1-L8 -import { Address } from '@ethereumjs/util' -import { Chain, Common, Hardfork } from '@ethereumjs/common' -import { LegacyTransaction } from '@ethereumjs/tx' -import { VM } from '@ethereumjs/vm' +import { Common, Hardfork, Mainnet } from '@ethereumjs/common' +import { createLegacyTx } from '@ethereumjs/tx' +import { createZeroAddress } from '@ethereumjs/util' +import { VM, runTx } from '@ethereumjs/vm' const main = async () => { - const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Shanghai }) + const common = new Common({ chain: Mainnet, hardfork: Hardfork.Shanghai }) const vm = await VM.create({ common }) ``` @@ -262,27 +265,31 @@ For initializing a custom genesis state you can use the `genesisState` construct ```ts // ./examples/vmWithGenesisState.ts -import { Blockchain } from '@ethereumjs/blockchain' import { Chain } from '@ethereumjs/common' import { getGenesis } from '@ethereumjs/genesis' -import { Address } from '@ethereumjs/util' +import { createAddressFromString } from '@ethereumjs/util' import { VM } from '@ethereumjs/vm' const main = async () => { const genesisState = getGenesis(Chain.Mainnet) - const blockchain = await Blockchain.create({ genesisState }) - const vm = await VM.create({ blockchain, genesisState }) + const vm = await VM.create() + await vm.stateManager.generateCanonicalGenesis!(genesisState) const account = await vm.stateManager.getAccount( - Address.fromString('0x000d836201318ec6899a67540690382780743280'), + createAddressFromString('0x000d836201318ec6899a67540690382780743280'), ) + + if (account === undefined) { + throw new Error('Account does not exist: failed to import genesis state') + } + console.log( `This balance for account 0x000d836201318ec6899a67540690382780743280 in this chain's genesis state is ${Number( account?.balance, )}`, ) } -main() +void main() ``` Genesis state can be configured to contain both EOAs as well as (system) contracts with initial storage values set. @@ -301,15 +308,15 @@ with the respective EIPs, e.g.: ```ts // ./examples/vmWithEIPs.ts -import { Chain, Common } from '@ethereumjs/common' +import { Common, Mainnet } from '@ethereumjs/common' import { VM } from '@ethereumjs/vm' const main = async () => { - const common = new Common({ chain: Chain.Mainnet, eips: [3074] }) + const common = new Common({ chain: Mainnet, eips: [7702] }) const vm = await VM.create({ common }) - console.log(`EIP 3074 is active in the VM - ${vm.common.isActivatedEIP(3074)}`) + console.log(`EIP 7702 is active in the VM - ${vm.common.isActivatedEIP(7702)}`) } -main() +void main() ``` For a list with supported EIPs see the [@ethereumjs/evm](https://github.com/ethereumjs/ethereumjs-monorepo/tree/master/packages/evm) documentation. @@ -345,16 +352,17 @@ To run VM/EVM related EIP-4844 functionality you have to activate the EIP in the ```ts // ./examples/vmWith4844.ts -import { Common, Chain, Hardfork } from '@ethereumjs/common' +import { Common, Hardfork, Mainnet } from '@ethereumjs/common' + import { VM } from '../src/vm.js' const main = async () => { - const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Shanghai, eips: [4844] }) + const common = new Common({ chain: Mainnet, hardfork: Hardfork.Shanghai, eips: [4844] }) const vm = await VM.create({ common }) console.log(`4844 is active in the VM - ${vm.common.isActivatedEIP(4844)}`) } -main() +void main() ``` EIP-4844 comes with a new opcode `BLOBHASH` and adds a new point evaluation precompile at address `0x14` in the underlying `@ethereumjs/evm` package. diff --git a/packages/wallet/README.md b/packages/wallet/README.md index 63b21d4666a..bdd4ba03cc3 100644 --- a/packages/wallet/README.md +++ b/packages/wallet/README.md @@ -35,7 +35,7 @@ You can import the `Wallet` class like this Node.js / ES6: ```js -// ./examples/wallet.js +// ./examples/wallet.cjs const { Wallet } = require('@ethereumjs/wallet') @@ -61,7 +61,7 @@ Importing various third party wallets is possible through the `thirdparty` submo Node.js / ES5: ```js -// ./examples/thirdparty.js +// ./examples/thirdparty.cjs const { thirdparty } = require('@ethereumjs/wallet') @@ -89,12 +89,12 @@ To use BIP32 HD wallets, first include the `hdkey` submodule: Node.js / ES5: ```js -// ./examples/hdKey.js +// ./examples/hdKey.cjs const { hdkey } = require('@ethereumjs/wallet') const wallet = hdkey.EthereumHDKey.fromMnemonic( - 'clown galaxy face oxygen birth round modify fame correct stumble kind excess' + 'clown galaxy face oxygen birth round modify fame correct stumble kind excess', ) console.log(wallet.getWallet().getAddressString()) // Should print an Ethereum address ``` @@ -107,7 +107,7 @@ ESM / TypeScript: import { hdkey } from '@ethereumjs/wallet' const wallet = hdkey.EthereumHDKey.fromMnemonic( - 'clown galaxy face oxygen birth round modify fame correct stumble kind excess' + 'clown galaxy face oxygen birth round modify fame correct stumble kind excess', ) console.log(wallet.getWallet().getAddressString()) // Should print an Ethereum address ```