From 1312c9c4f0777d713e8d38f477d24f0dcd2413c2 Mon Sep 17 00:00:00 2001 From: Scorbajio Date: Mon, 26 Aug 2024 03:58:04 -0700 Subject: [PATCH] Update readmes and examples (#3611) * Update block README examples from examples files * Update blockchain README examples from examples files * Update common README examples from examples files * Update devp2p README examples from examples files * Update ethash README examples from examples files * Update evm README examples from examples files * Update genesis README examples from examples files * Update rlp README examples from examples files * Update statemanager README examples from examples files * Update trie README examples from examples files * Update tx README examples from examples files * Update util README examples from examples files * Update vm README examples from examples files * Update wallet README examples from examples files --- packages/block/README.md | 111 ++++++++++++++++---------------- packages/blockchain/README.md | 27 ++++---- packages/common/README.md | 77 +++++++++------------- packages/devp2p/README.md | 24 +++---- packages/ethash/README.md | 18 ++++-- packages/evm/README.md | 50 +++++++------- packages/genesis/README.md | 6 +- packages/rlp/README.md | 2 +- packages/statemanager/README.md | 53 +++++++-------- packages/trie/README.md | 70 ++++++++++---------- packages/tx/README.md | 84 ++++++++++++------------ packages/util/README.md | 16 ++--- packages/vm/README.md | 98 +++++++++++++++------------- packages/wallet/README.md | 10 +-- 14 files changed, 323 insertions(+), 323 deletions(-) diff --git a/packages/block/README.md b/packages/block/README.md index c78a8be8ac..4e4548cb5e 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 { createBlob4844Tx } 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 = createBlob4844Tx( + { 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. @@ -223,21 +226,20 @@ Starting with v5.3.0 this library supports requests to the consensus layer which ```ts // ./examples/6110Requests.ts -import { Chain, Common, Hardfork } from '@ethereumjs/common' -import { Block } from '@ethereumjs/block' +import { createBlock, genRequestsTrieRoot } from '@ethereumjs/block' +import { Common, Hardfork, Mainnet } from '@ethereumjs/common' import { - bytesToBigInt, - DepositRequest, - randomBytes, type CLRequest, type CLRequestType, + DepositRequest, + bytesToBigInt, + randomBytes, } from '@ethereumjs/util' const main = async () => { const common = new Common({ - chain: Chain.Mainnet, - hardfork: Hardfork.Cancun, - eips: [7685, 4788], + chain: Mainnet, + hardfork: Hardfork.Prague, }) const depositRequestData = { @@ -249,9 +251,9 @@ const main = async () => { } const request = DepositRequest.fromRequestData(depositRequestData) as CLRequest const requests = [request] - const requestsRoot = await Block.genRequestsTrieRoot(requests) + const requestsRoot = await genRequestsTrieRoot(requests) - const block = Block.fromBlockData( + const block = createBlock( { requests, header: { requestsRoot }, @@ -261,11 +263,11 @@ const main = async () => { console.log( `Instantiated block with ${ block.requests?.length - } request, requestTrieValid=${await block.requestsTrieIsValid()}`, + } deposit request, requestTrieValid=${await block.requestsTrieIsValid()}`, ) } -main() +void main() ``` Have a look at the EIP for some guidance on how to use and fill in the various deposit request parameters. @@ -328,19 +330,18 @@ Have a look at the EIP for some guidance on how to use and fill in the various w ```ts // ./examples/7251Requests.ts -import { Chain, Common, Hardfork } from '@ethereumjs/common' -import { Block } from '@ethereumjs/block' +import { createBlock, genRequestsTrieRoot } from '@ethereumjs/block' +import { Common, Hardfork, Mainnet } from '@ethereumjs/common' import { - bytesToBigInt, - ConsolidationRequest, - randomBytes, type CLRequest, type CLRequestType, + ConsolidationRequest, + randomBytes, } from '@ethereumjs/util' const main = async () => { const common = new Common({ - chain: Chain.Mainnet, + chain: Mainnet, hardfork: Hardfork.Prague, }) @@ -353,9 +354,9 @@ const main = async () => { consolidationRequestData, ) as CLRequest const requests = [request] - const requestsRoot = await Block.genRequestsTrieRoot(requests) + const requestsRoot = await genRequestsTrieRoot(requests) - const block = Block.fromBlockData( + const block = createBlock( { requests, header: { requestsRoot }, @@ -369,7 +370,7 @@ const main = async () => { ) } -main() +void main() ``` Have a look at the EIP for some guidance on how to use and fill in the various deposit request parameters. @@ -389,15 +390,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 +411,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 +451,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 b3f67525da..447615ac59 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 79abe06cb6..55a40e9a1b 100644 --- a/packages/common/README.md +++ b/packages/common/README.md @@ -42,13 +42,13 @@ All parameters can be accessed through the `Common` class, instantiated with an ```ts // ./examples/common.ts#L1-L7 -import { Chain, Common, Hardfork } from '@ethereumjs/common' +import { Common, Hardfork, Mainnet, createCustomCommon } from '@ethereumjs/common' // With enums: -const commonWithEnums = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.London }) +const commonWithEnums = new Common({ chain: Mainnet, hardfork: Hardfork.London }) -// (also possible with directly passing in strings:) -const commonWithStrings = new Common({ chain: 'mainnet', hardfork: 'london' }) +// Instantiate with the chain (and the default hardfork) +let c = new Common({ chain: Mainnet }) ``` If no hardfork is provided, the common is initialized with the default hardfork. @@ -60,21 +60,17 @@ Here are some simple usage examples: ```ts // ./examples/common.ts#L9-L23 -// Instantiate with the chain (and the default hardfork) -let c = new Common({ chain: Chain.Mainnet }) -console.log(`The gas price for ecAdd is ${c.param('gasPrices', 'ecAddGas')}`) // 500 - -// Chain and hardfork provided -c = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Byzantium }) -console.log(`The miner reward under PoW on Byzantium us ${c.param('pow', 'minerReward')}`) // 3000000000000000000 - // Get bootstrap nodes for chain/network console.log('Below are the known bootstrap nodes') console.log(c.bootstrapNodes()) // Array with current nodes // Instantiate with an EIP activated -c = new Common({ chain: Chain.Mainnet, eips: [4844] }) +c = new Common({ chain: Mainnet, eips: [4844] }) console.log(`EIP 4844 is active -- ${c.isActivatedEIP(4844)}`) + +// Instantiate common with custom chainID +const commonWithCustomChainId = createCustomCommon({ chainId: 1234 }, Mainnet) +console.log(`The current chain ID is ${commonWithCustomChainId.chainId}`) ``` ### Custom Cryptography Primitives (WASM) @@ -98,23 +94,23 @@ The following is an example using the [@polkadot/wasm-crypto](https://github.com ```ts // ./examples/customCrypto.ts +import { createBlock } from '@ethereumjs/block' +import { Common, Mainnet } from '@ethereumjs/common' import { keccak256, waitReady } from '@polkadot/wasm-crypto' -import { Chain, Common } from '@ethereumjs/common' -import { Block } from '@ethereumjs/block' const main = async () => { // @polkadot/wasm-crypto specific initialization await waitReady() - const common = new Common({ chain: Chain.Mainnet, customCrypto: { keccak256 } }) - const block = Block.fromBlockData({}, { common }) + const common = new Common({ chain: Mainnet, customCrypto: { keccak256 } }) + const block = createBlock({}, { common }) // Method invocations within EthereumJS library instantiations where the common // instance above is passed will now use the custom keccak256 implementation console.log(block.hash()) } -main() +void main() ``` ### Example 2: KZG @@ -126,20 +122,20 @@ to initialize (assuming you are using the `c-kzg` package as your KZG cryptograp ```ts // ./examples/initKzg.ts +import { Common, Hardfork, Mainnet } from '@ethereumjs/common' import { loadKZG } from 'kzg-wasm' -import { Common, Chain, Hardfork } from '@ethereumjs/common' const main = async () => { const kzg = await loadKZG() const common = new Common({ - chain: Chain.Mainnet, + chain: Mainnet, hardfork: Hardfork.Cancun, customCrypto: { kzg }, }) console.log(common.customCrypto.kzg) // Should print the initialized KZG interface } -main() +void main() ``` ## Browser @@ -241,10 +237,6 @@ There is a dedicated `Common.custom()` static constructor which allows for an ea ```ts // ./examples/common.ts#L25-L27 - -// Instantiate common with custom chainID -const commonWithCustomChainId = Common.custom({ chainId: 1234 }) -console.log(`The current chain ID is ${commonWithCustomChainId.chainId}`) ``` The `custom()` method also takes a string as a first input (instead of a dictionary). This can be used in combination with the `CustomChain` enum dict which allows for the selection of predefined supported custom chains for an easier `Common` setup of these supported chains: @@ -273,11 +265,12 @@ values to the constructor using the `chain` parameter or the `setChain()` method ```ts // ./examples/customChain.ts -import { Common } from '@ethereumjs/common' +import { Common, Mainnet, createCustomCommon } from '@ethereumjs/common' + import myCustomChain1 from './genesisData/testnet.json' // Add custom chain config -const common1 = new Common({ chain: myCustomChain1 }) +const common1 = createCustomCommon(myCustomChain1, Mainnet) console.log(`Common is instantiated with custom chain parameters - ${common1.chainName()}`) ``` @@ -291,23 +284,15 @@ 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 +// ./examples/customChain.ts + +import { Common, Mainnet, createCustomCommon } from '@ethereumjs/common' -import { Common } from '@ethereumjs/common' import myCustomChain1 from './genesisData/testnet.json' -import myCustomChain2 from './genesisData/testnet2.json' -// Add two custom chains, initial mainnet activation -const common1 = new Common({ chain: 'mainnet', customChains: [myCustomChain1, myCustomChain2] }) -console.log(`Common is instantiated with mainnet parameters - ${common1.chainName()}`) -common1.setChain('testnet1') -console.log(`Common is set to use testnet parameters - ${common1.chainName()}`) -// Add two custom chains, activate customChain1 -const common2 = new Common({ - chain: 'testnet2', - customChains: [myCustomChain1, myCustomChain2], -}) - -console.log(`Common is instantiated with testnet2 parameters - ${common1.chainName()}`) + +// Add custom chain config +const common1 = createCustomCommon(myCustomChain1, Mainnet) +console.log(`Common is instantiated with custom chain parameters - ${common1.chainName()}`) ``` Starting with v3 custom genesis states should be passed to the [Blockchain](../blockchain/) library directly. @@ -321,14 +306,14 @@ common from such configuration in the following manner: ```ts // ./examples/fromGeth.ts -import { Common } from '@ethereumjs/common' +import { createCommonFromGethGenesis } from '@ethereumjs/common' import { hexToBytes } from '@ethereumjs/util' import genesisJson from './genesisData/post-merge.json' const genesisHash = hexToBytes('0x3b8fb240d288781d4aac94d3fd16809ee413bc99294a085798a589dae51ddd4a') // Load geth genesis json file into lets say `genesisJson` and optional `chain` and `genesisHash` -const common = Common.fromGethGenesis(genesisJson, { chain: 'customChain', genesisHash }) +const common = createCommonFromGethGenesis(genesisJson, { chain: 'customChain', genesisHash }) // If you don't have `genesisHash` while initiating common, you can later configure common (for e.g. // after calculating it via `blockchain`) common.setForkHashes(genesisHash) @@ -343,10 +328,10 @@ The `hardfork` can be set in constructor like this: ```ts // ./examples/common.ts#L1-L4 -import { Chain, Common, Hardfork } from '@ethereumjs/common' +import { Common, Hardfork, Mainnet, createCustomCommon } from '@ethereumjs/common' // With enums: -const commonWithEnums = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.London }) +const commonWithEnums = new Common({ chain: Mainnet, hardfork: Hardfork.London }) ``` ### Active Hardforks diff --git a/packages/devp2p/README.md b/packages/devp2p/README.md index 7021acefeb..3e2696f97b 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,12 +165,12 @@ 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', ) @@ -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 41346153d9..94b0a6827f 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 fa08770458..b329373810 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), }) @@ -106,12 +108,12 @@ The following code allows to run precompiles in isolation, e.g. for testing purp ```ts // ./examples/precompile.ts -import { Chain, Common, Hardfork } from '@ethereumjs/common' -import { EVM, getActivePrecompiles } from '@ethereumjs/evm' +import { Common, Hardfork, Mainnet } from '@ethereumjs/common' +import { createEVM, getActivePrecompiles } from '@ethereumjs/evm' import { bytesToHex, hexToBytes } from '@ethereumjs/util' const main = async () => { - const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Prague }) + const common = new Common({ chain: Mainnet, hardfork: Hardfork.Prague }) // Taken from test/eips/precompiles/bls/add_G1_bls.json const data = hexToBytes( @@ -119,7 +121,7 @@ const main = async () => { ) const gasLimit = BigInt(5000000) - const evm = await EVM.create({ common }) + const evm = await createEVM({ common }) const precompile = getActivePrecompiles(common).get('000000000000000000000000000000000000000b')! const callData = { @@ -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 f030dd290a..4ad4845aba 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 9532de06b6..7b2c8dbcf9 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 e25fa65294..05b5bdf9bf 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() @@ -59,7 +58,7 @@ const main = async () => { }`, ) } -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 @@ -124,9 +123,9 @@ const main = async () => { 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 d77b074c92..a16399d1cb 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 d4c96f2f07..a9912c346a 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 { createBlob4844Tx } 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 = createBlob4844Tx(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 { createFeeMarket1559Tx } 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 = createFeeMarket1559Tx(txData, { common }) console.log(bytesToHex(tx.hash())) // 0x6f9ef69ccb1de1aea64e511efd6542541008ced321887937c95b03779358ec8a ``` @@ -221,18 +221,19 @@ The following is a simple example how to use an `EOACodeEIP7702Transaction` with ```ts // ./examples/EOACodeTx.ts -import { Chain, Common, Hardfork } from '@ethereumjs/common' -import { EOACodeEIP7702Transaction } from '@ethereumjs/tx' +import { Common, Hardfork, Mainnet } from '@ethereumjs/common' +import { createEOACode7702Tx } from '@ethereumjs/tx' + import type { PrefixedHexString } from '@ethereumjs/util' const ones32 = `0x${'01'.repeat(32)}` as PrefixedHexString -const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Cancun, eips: [7702] }) -const tx = EOACodeEIP7702Transaction.fromTxData( +const common = new Common({ chain: Mainnet, hardfork: Hardfork.Cancun, eips: [7702] }) +const tx = createEOACode7702Tx( { authorizationList: [ { - chainId: '0x1', + chainId: '0x2', address: `0x${'20'.repeat(20)}`, nonce: ['0x1'], yParity: '0x1', @@ -262,11 +263,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 { createAccessList2930Tx } 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 +292,7 @@ const txData = { type: '0x01', } -const tx = AccessListEIP2930Transaction.fromTxData(txData, { common }) +const tx = createAccessList2930Tx(txData, { common }) console.log(bytesToHex(tx.hash())) // 0x9150cdebad74e88b038e6c6b964d99af705f9c0883d7f0bbc0f3e072358f5b1d ``` @@ -310,12 +311,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 +325,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 +343,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 transaction -const tx = TransactionFactory.fromTxData(txData, { common }) +const tx = createTxFromTxData(txData, { common }) if (tx.supports(Capability.EIP1559FeeMarket)) { console.log( @@ -377,13 +378,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 +395,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 63ff8bdf8b..c3a6d890a7 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', @@ -50,9 +50,9 @@ For Verkle or other contexts it can be useful to create partial accounts not con ```ts // ./examples/accountPartial.ts -import { Account } from '@ethereumjs/util' +import { createPartialAccount } from '@ethereumjs/util' -const account = Account.fromPartialAccountData({ +const account = createPartialAccount({ nonce: '0x02', balance: '0x0384', }) @@ -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`) ``` @@ -162,12 +162,12 @@ import { bytesToHex, ecrecover, hexToBytes } from '@ethereumjs/util' const chainId = BigInt(3) // Ropsten -const echash = hexToBytes('0x82ff40c0a986c6a5cfad4ddf4c3aa6996f1a7837f9c398e17e5de5cbd5a12b28') +const ecHash = hexToBytes('0x82ff40c0a986c6a5cfad4ddf4c3aa6996f1a7837f9c398e17e5de5cbd5a12b28') const r = hexToBytes('0x99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1abe9') const s = hexToBytes('0x129ff05af364204442bdb53ab6f18a99ab48acc9326fa689f228040429e3ca66') const v = BigInt(41) -const pubkey = ecrecover(echash, v, r, s, chainId) +const pubkey = ecrecover(ecHash, v, r, s, chainId) console.log(`Recovered public key ${bytesToHex(pubkey)} from valid signature values`) ``` diff --git a/packages/vm/README.md b/packages/vm/README.md index 8809920c1e..29d4cc7f16 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 validation 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 validation 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 63b21d4666..bdd4ba03cc 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 ```