From 53f14e0a30fd303c3f509a1e42e5b3431891fea8 Mon Sep 17 00:00:00 2001 From: Ryan Ghods Date: Tue, 7 Dec 2021 16:45:36 -1000 Subject: [PATCH 1/3] client: allow block number arg in rpc --- packages/client/lib/rpc/modules/eth.ts | 154 ++++++------------ packages/client/test/rpc/eth/call.spec.ts | 58 ++++--- .../client/test/rpc/eth/estimateGas.spec.ts | 59 ++++--- .../client/test/rpc/eth/getBalance.spec.ts | 98 +++++------ .../test/rpc/eth/getBlockByNumber.spec.ts | 30 +--- packages/client/test/rpc/eth/getCode.spec.ts | 56 ++++--- .../client/test/rpc/eth/getStorageAt.spec.ts | 135 ++++++++------- .../test/rpc/eth/getTransactionCount.spec.ts | 83 +++++----- 8 files changed, 323 insertions(+), 350 deletions(-) diff --git a/packages/client/lib/rpc/modules/eth.ts b/packages/client/lib/rpc/modules/eth.ts index e08dfd69cd..75681dfff1 100644 --- a/packages/client/lib/rpc/modules/eth.ts +++ b/packages/client/lib/rpc/modules/eth.ts @@ -255,6 +255,41 @@ const jsonRpcReceipt = async ( : undefined, }) +/** + * Get block by option + */ +const getBlockByOption = async (blockOpt: string, chain: Chain) => { + if (blockOpt === 'pending') { + throw { + code: INVALID_PARAMS, + message: `"pending" is not yet supported`, + } + } + + let block: Block + const latest = chain.blocks.latest ?? (await chain.getLatestBlock()) + + if (blockOpt === 'latest') { + block = latest + } else if (blockOpt === 'earliest') { + block = await chain.getBlock(new BN(0)) + } else { + const blockNumber = new BN(toBuffer(blockOpt)) + if (blockNumber.eq(latest.header.number)) { + block = latest + } else if (blockNumber.gt(latest.header.number)) { + throw { + code: INVALID_PARAMS, + message: 'specified block greater than current height', + } + } else { + block = await chain.getBlock(blockNumber) + } + } + + return block +} + /** * eth_* RPC module * @memberof module:rpc/modules @@ -381,7 +416,6 @@ export class Eth { /** * Executes a new message call immediately without creating a transaction on the block chain. - * Currently only "latest" block is supported. * @param params An array of two parameters: * 1. The transaction object * * from (optional) - The address the transaction is sent from @@ -395,24 +429,14 @@ export class Eth { */ async call(params: [RpcTx, string]) { const [transaction, blockOpt] = params + const block = await getBlockByOption(blockOpt, this._chain) if (!this._vm) { throw new Error('missing vm') } - // use a copy of the vm in case new blocks are executed, - // and to not make any underlying changes during the call const vm = this._vm.copy() - - if (blockOpt !== 'latest') { - const latest = await vm.blockchain.getLatestHeader() - if (blockOpt !== bnToHex(latest.number)) { - throw { - code: INVALID_PARAMS, - message: `Currently only "latest" block supported`, - } - } - } + await vm.stateManager.setStateRoot(block.header.stateRoot) if (!transaction.gas) { // If no gas limit is specified use the last block gas limit as an upper bound. @@ -448,7 +472,6 @@ export class Eth { * The transaction will not be added to the blockchain. * Note that the estimate may be significantly more than the amount of gas actually used by the transaction, * for a variety of reasons including EVM mechanics and node performance. - * Currently only "latest" block is supported. * @param params An array of two parameters: * 1. The transaction object * * from (optional) - The address the transaction is sent from @@ -462,23 +485,14 @@ export class Eth { */ async estimateGas(params: [RpcTx, string]) { const [transaction, blockOpt] = params + const block = await getBlockByOption(blockOpt, this._chain) if (!this._vm) { throw new Error('missing vm') } - // use a copy of the vm in case new blocks are executed const vm = this._vm.copy() - - if (blockOpt !== 'latest') { - const latest = await vm.blockchain.getLatestHeader() - if (blockOpt !== bnToHex(latest.number)) { - throw { - code: INVALID_PARAMS, - message: `Currently only "latest" block supported`, - } - } - } + await vm.stateManager.setStateRoot(block.header.stateRoot) if (!transaction.gas) { // If no gas limit is specified use the last block gas limit as an upper bound. @@ -506,33 +520,22 @@ export class Eth { /** * Returns the balance of the account at the given address. - * Currently only "latest" block is supported. * @param params An array of two parameters: * 1. address of the account * 2. integer block number, or the string "latest", "earliest" or "pending" */ async getBalance(params: [string, string]) { const [addressHex, blockOpt] = params + const address = Address.fromString(addressHex) + const block = await getBlockByOption(blockOpt, this._chain) if (!this._vm) { throw new Error('missing vm') } - // use a copy of the vm in case new blocks are sync'd const vm = this._vm.copy() - - if (blockOpt !== 'latest') { - const latest = await vm.blockchain.getLatestHeader() - if (blockOpt !== bnToHex(latest.number)) { - throw { - code: INVALID_PARAMS, - message: `Currently only "latest" block supported`, - } - } - } - - const address = Address.fromString(addressHex) - const account: Account = await vm.stateManager.getAccount(address) + await vm.stateManager.setStateRoot(block.header.stateRoot) + const account = await vm.stateManager.getAccount(address) return bnToHex(account.balance) } @@ -564,34 +567,7 @@ export class Eth { */ async getBlockByNumber(params: [string, boolean]) { const [blockOpt, includeTransactions] = params - const latest = this._chain.blocks.latest ?? (await this._chain.getLatestBlock()) - let block: Block - - if (blockOpt === 'pending') { - throw { - code: INVALID_PARAMS, - message: `"pending" is not yet supported`, - } - } - - if (blockOpt === 'latest') { - block = latest - } else if (blockOpt === 'earliest') { - block = await this._chain.getBlock(new BN(0)) - } else { - const blockNumber = new BN(toBuffer(blockOpt)) - if (blockNumber.eq(latest.header.number)) { - block = latest - } else if (blockNumber.gt(latest.header.number)) { - throw { - code: INVALID_PARAMS, - message: 'specified block greater than current height', - } - } else { - block = await this._chain.getBlock(blockNumber) - } - } - + const block = await getBlockByOption(blockOpt, this._chain) return await jsonRpcBlock(block, this._chain, includeTransactions) } @@ -614,30 +590,20 @@ export class Eth { /** * Returns code of the account at the given address. - * Currently only "latest" block is supported. * @param params An array of two parameters: * 1. address of the account * 2. integer block number, or the string "latest", "earliest" or "pending" */ async getCode(params: [string, string]) { const [addressHex, blockOpt] = params + const block = await getBlockByOption(blockOpt, this._chain) if (!this._vm) { throw new Error('missing vm') } - // use a copy of the vm in case new blocks are sync'd const vm = this._vm.copy() - - if (blockOpt !== 'latest') { - const latest = await vm.blockchain.getLatestHeader() - if (blockOpt !== bnToHex(latest.number)) { - throw { - code: INVALID_PARAMS, - message: `Currently only "latest" block supported`, - } - } - } + await vm.stateManager.setStateRoot(block.header.stateRoot) const address = Address.fromString(addressHex) const code = await vm.stateManager.getContractCode(address) @@ -646,7 +612,6 @@ export class Eth { /** * Returns the value from a storage position at a given address. - * Currently only "latest" block is supported. * @param params An array of three parameters: * 1. address of the storage * 2. integer of the position in the storage @@ -654,23 +619,14 @@ export class Eth { */ async getStorageAt(params: [string, string, string]) { const [addressHex, positionHex, blockOpt] = params + const block = await getBlockByOption(blockOpt, this._chain) if (!this._vm) { throw new Error('missing vm') } - // use a copy of the vm in case new blocks are executed const vm = this._vm.copy() - - if (blockOpt !== 'latest') { - const latest = await vm.blockchain.getLatestHeader() - if (blockOpt !== bnToHex(latest.number)) { - throw { - code: INVALID_PARAMS, - message: `Currently only "latest" block supported`, - } - } - } + await vm.stateManager.setStateRoot(block.header.stateRoot) const address = Address.fromString(addressHex) const storageTrie = await (vm.stateManager as any)._getStorageTrie(address) @@ -704,30 +660,20 @@ export class Eth { /** * Returns the number of transactions sent from an address. - * Currently only "latest" block is supported. * @param params An array of two parameters: * 1. address of the account * 2. integer block number, or the string "latest", "earliest" or "pending" */ async getTransactionCount(params: [string, string]) { const [addressHex, blockOpt] = params + const block = await getBlockByOption(blockOpt, this._chain) if (!this._vm) { throw new Error('missing vm') } - // use a copy of the vm in case new blocks are executed const vm = this._vm.copy() - - if (blockOpt !== 'latest') { - const latest = await vm.blockchain.getLatestHeader() - if (blockOpt !== bnToHex(latest.number)) { - throw { - code: INVALID_PARAMS, - message: `Currently only "latest" block supported`, - } - } - } + await vm.stateManager.setStateRoot(block.header.stateRoot) const address = Address.fromString(addressHex) const account: Account = await vm.stateManager.getAccount(address) diff --git a/packages/client/test/rpc/eth/call.spec.ts b/packages/client/test/rpc/eth/call.spec.ts index 31429aa1b3..8c20a7f89b 100644 --- a/packages/client/test/rpc/eth/call.spec.ts +++ b/packages/client/test/rpc/eth/call.spec.ts @@ -1,7 +1,8 @@ import tape from 'tape' -import { Address, BN, bufferToHex } from 'ethereumjs-util' +import { Block } from '@ethereumjs/block' import Blockchain from '@ethereumjs/blockchain' import { Transaction } from '@ethereumjs/tx' +import { Address, BN, bnToHex, bufferToHex } from 'ethereumjs-util' import { FullSynchronizer } from '../../../lib/sync' import { INVALID_PARAMS } from '../../../lib/rpc/error-code' import { startRPC, createManager, createClient, params, baseRequest } from '../helpers' @@ -10,40 +11,57 @@ import { checkError } from '../util' const method = 'eth_call' tape(`${method}: call with valid arguments`, async (t) => { - const blockchain = await Blockchain.create() + const blockchain = await Blockchain.create({ validateBlocks: false, validateConsensus: false }) const client = createClient({ blockchain, includeVM: true }) const manager = createManager(client) const server = startRPC(manager.getMethods()) const service = client.services.find((s) => s.name === 'eth') - const vm = (service!.synchronizer as FullSynchronizer).execution.vm + const { vm } = (service!.synchronizer as FullSynchronizer).execution // genesis address with balance const address = Address.fromString('0xccfd725760a68823ff1e062f4cc97e1360e8d997') // contract: /* - // SPDX-License-Identifier: MIT - pragma solidity ^0.7.4; - - contract HelloWorld { - function myAddress() public view returns (address addr) { - return msg.sender; - } + // SPDX-License-Identifier: MIT + pragma solidity ^0.7.4; + + contract HelloWorld { + function myAddress() public view returns (address addr) { + return msg.sender; } - */ + } + */ const data = '0x6080604052348015600f57600080fd5b50609d8061001e6000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c806326b85ee114602d575b600080fd5b6033605f565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b60003390509056fea2646970667358221220455a67424337c6c5783846576348cb04caa9cf6f3e7def201c1f3fbc54aa373a64736f6c63430007060033' - // construct tx - const tx = Transaction.fromTxData({ gasLimit: 2000000, data }, { freeze: false }) + // construct block with tx + const gasLimit = 2000000 + const tx = Transaction.fromTxData({ gasLimit, data }, { freeze: false }) tx.getSenderAddress = () => { return address } + const parent = await blockchain.getLatestHeader() + const block = Block.fromBlockData( + { + header: { + parentHash: parent.hash(), + number: 1, + gasLimit, + }, + }, + { calcDifficultyFromHeader: parent } + ) + block.transactions[0] = tx // deploy contract - const { createdAddress } = await vm.runTx({ tx }) + let ranBlock: Block | undefined = undefined + vm.once('afterBlock', (result: any) => (ranBlock = result.block)) + const result = await vm.runBlock({ block, generate: true, skipBlockValidation: true }) + const { createdAddress } = result.results[0] + await vm.blockchain.putBlock(ranBlock!) // get return value const funcHash = '26b85ee1' // myAddress() @@ -51,7 +69,7 @@ tape(`${method}: call with valid arguments`, async (t) => { to: createdAddress!.toString(), from: address.toString(), data: `0x${funcHash}`, - gasLimit: `0x${new BN(53000).toString(16)}`, + gasLimit: bnToHex(new BN(53000)), } const estimateTx = Transaction.fromTxData(estimateTxData, { freeze: false }) estimateTx.getSenderAddress = () => { @@ -68,11 +86,7 @@ tape(`${method}: call with valid arguments`, async (t) => { const req = params(method, [{ ...estimateTxData, gas: estimateTxData.gasLimit }, 'latest']) const expectRes = (res: any) => { const msg = 'should return the correct return value' - if (res.body.result === bufferToHex(execResult.returnValue)) { - t.pass(msg) - } else { - throw new Error(msg) - } + t.equal(res.body.result, bufferToHex(execResult.returnValue), msg) } await baseRequest(t, server, req, 200, expectRes) }) @@ -92,10 +106,10 @@ tape(`${method}: call with unsupported block argument`, async (t) => { to: address.toString(), from: address.toString(), data: `0x${funcHash}`, - gasLimit: `0x${new BN(53000).toString(16)}`, + gasLimit: bnToHex(new BN(53000)), } const req = params(method, [{ ...estimateTxData, gas: estimateTxData.gasLimit }, 'pending']) - const expectRes = checkError(t, INVALID_PARAMS, 'Currently only "latest" block supported') + const expectRes = checkError(t, INVALID_PARAMS, '"pending" is not yet supported') await baseRequest(t, server, req, 200, expectRes) }) diff --git a/packages/client/test/rpc/eth/estimateGas.spec.ts b/packages/client/test/rpc/eth/estimateGas.spec.ts index b16a926195..84c5b0fddc 100644 --- a/packages/client/test/rpc/eth/estimateGas.spec.ts +++ b/packages/client/test/rpc/eth/estimateGas.spec.ts @@ -1,7 +1,8 @@ import tape from 'tape' -import { Address, BN } from 'ethereumjs-util' +import { Block } from '@ethereumjs/block' import Blockchain from '@ethereumjs/blockchain' import { Transaction } from '@ethereumjs/tx' +import { Address, BN, bnToHex } from 'ethereumjs-util' import { FullSynchronizer } from '../../../lib/sync' import { INVALID_PARAMS } from '../../../lib/rpc/error-code' import { startRPC, createManager, createClient, params, baseRequest } from '../helpers' @@ -10,40 +11,58 @@ import { checkError } from '../util' const method = 'eth_estimateGas' tape(`${method}: call with valid arguments`, async (t) => { - const blockchain = await Blockchain.create() + const blockchain = await Blockchain.create({ validateBlocks: false, validateConsensus: false }) const client = createClient({ blockchain, includeVM: true }) const manager = createManager(client) const server = startRPC(manager.getMethods()) const service = client.services.find((s) => s.name === 'eth') - const vm = (service!.synchronizer as FullSynchronizer).execution.vm + const { vm } = (service!.synchronizer as FullSynchronizer).execution + await vm.stateManager.generateCanonicalGenesis() // genesis address with balance const address = Address.fromString('0xccfd725760a68823ff1e062f4cc97e1360e8d997') // contract: /* - // SPDX-License-Identifier: MIT - pragma solidity ^0.7.4; - - contract HelloWorld { - function myAddress() public view returns (address addr) { - return msg.sender; - } + // SPDX-License-Identifier: MIT + pragma solidity ^0.7.4; + + contract HelloWorld { + function myAddress() public view returns (address addr) { + return msg.sender; } - */ + } + */ const data = '0x6080604052348015600f57600080fd5b50609d8061001e6000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c806326b85ee114602d575b600080fd5b6033605f565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b60003390509056fea2646970667358221220455a67424337c6c5783846576348cb04caa9cf6f3e7def201c1f3fbc54aa373a64736f6c63430007060033' - // construct tx - const tx = Transaction.fromTxData({ gasLimit: 2000000, data }, { freeze: false }) + // construct block with tx + const gasLimit = 2000000 + const tx = Transaction.fromTxData({ gasLimit, data }, { freeze: false }) tx.getSenderAddress = () => { return address } + const parent = await blockchain.getLatestHeader() + const block = Block.fromBlockData( + { + header: { + parentHash: parent.hash(), + number: 1, + gasLimit, + }, + }, + { calcDifficultyFromHeader: parent } + ) + block.transactions[0] = tx // deploy contract - const { createdAddress } = await vm.runTx({ tx }) + let ranBlock: Block | undefined = undefined + vm.once('afterBlock', (result: any) => (ranBlock = result.block)) + const result = await vm.runBlock({ block, generate: true, skipBlockValidation: true }) + const { createdAddress } = result.results[0] + await vm.blockchain.putBlock(ranBlock!) // get gas estimate const funcHash = '26b85ee1' // myAddress() @@ -51,7 +70,7 @@ tape(`${method}: call with valid arguments`, async (t) => { to: createdAddress!.toString(), from: address.toString(), data: `0x${funcHash}`, - gasLimit: `0x${new BN(53000).toString(16)}`, + gasLimit: bnToHex(new BN(53000)), } const estimateTx = Transaction.fromTxData(estimateTxData, { freeze: false }) estimateTx.getSenderAddress = () => { @@ -68,11 +87,7 @@ tape(`${method}: call with valid arguments`, async (t) => { const req = params(method, [{ ...estimateTxData, gas: estimateTxData.gasLimit }, 'latest']) const expectRes = (res: any) => { const msg = 'should return the correct gas estimate' - if (res.body.result === `0x${gasUsed.toString(16)}`) { - t.pass(msg) - } else { - throw new Error(msg) - } + t.equal(res.body.result, bnToHex(gasUsed), msg) } await baseRequest(t, server, req, 200, expectRes) }) @@ -92,10 +107,10 @@ tape(`${method}: call with unsupported block argument`, async (t) => { to: address.toString(), from: address.toString(), data: `0x${funcHash}`, - gasLimit: `0x${new BN(53000).toString(16)}`, + gasLimit: bnToHex(new BN(53000)), } const req = params(method, [{ ...estimateTxData, gas: estimateTxData.gasLimit }, 'pending']) - const expectRes = checkError(t, INVALID_PARAMS, 'Currently only "latest" block supported') + const expectRes = checkError(t, INVALID_PARAMS, '"pending" is not yet supported') await baseRequest(t, server, req, 200, expectRes) }) diff --git a/packages/client/test/rpc/eth/getBalance.spec.ts b/packages/client/test/rpc/eth/getBalance.spec.ts index e459ed5da6..b4ec8e592c 100644 --- a/packages/client/test/rpc/eth/getBalance.spec.ts +++ b/packages/client/test/rpc/eth/getBalance.spec.ts @@ -1,7 +1,8 @@ import tape from 'tape' -import { Address, BN, toBuffer } from 'ethereumjs-util' +import { Block } from '@ethereumjs/block' import Blockchain from '@ethereumjs/blockchain' import { Transaction } from '@ethereumjs/tx' +import { Address, BN, toBuffer, bnToHex } from 'ethereumjs-util' import { FullSynchronizer } from '../../../lib/sync' import { INVALID_PARAMS } from '../../../lib/rpc/error-code' import { startRPC, createManager, createClient, params, baseRequest } from '../helpers' @@ -9,34 +10,6 @@ import { checkError } from '../util' const method = 'eth_getBalance' -tape(`${method}: call with valid arguments`, async (t) => { - const blockchain = await Blockchain.create() - - const client = createClient({ blockchain, includeVM: true }) - const manager = createManager(client) - const server = startRPC(manager.getMethods()) - - // since synchronizer.run() is not executed in the mock setup, - // manually run stateManager.generateCanonicalGenesis() - const vm = (client.services[0].synchronizer as FullSynchronizer).execution.vm - await vm.stateManager.generateCanonicalGenesis() - - // genesis address with balance - const address = Address.fromString('0xccfd725760a68823ff1e062f4cc97e1360e8d997') - - // verify balance is genesis amount - const req = params(method, [address.toString(), 'latest']) - const expectRes = (res: any) => { - const msg = 'should return the correct balance' - if (res.body.result === '0x15ac56edc4d12c0000') { - t.pass(msg) - } else { - throw new Error(msg) - } - } - await baseRequest(t, server, req, 200, expectRes) -}) - tape(`${method}: ensure balance deducts after a tx`, async (t) => { const blockchain = await Blockchain.create() @@ -45,7 +18,7 @@ tape(`${method}: ensure balance deducts after a tx`, async (t) => { const server = startRPC(manager.getMethods()) const service = client.services.find((s) => s.name === 'eth') - const vm = (service!.synchronizer as FullSynchronizer).execution.vm + const { vm } = (service!.synchronizer as FullSynchronizer).execution // since synchronizer.run() is not executed in the mock setup, // manually run stateManager.generateCanonicalGenesis() @@ -54,27 +27,54 @@ tape(`${method}: ensure balance deducts after a tx`, async (t) => { // genesis address with balance const address = Address.fromString('0xccfd725760a68823ff1e062f4cc97e1360e8d997') - // construct tx + // verify balance is genesis amount + const genesisBalance = new BN(toBuffer('0x15ac56edc4d12c0000')) + let req = params(method, [address.toString(), 'latest']) + let expectRes = (res: any) => { + const msg = 'should return the correct genesis balance' + t.equal(res.body.result, bnToHex(genesisBalance), msg) + } + await baseRequest(t, server, req, 200, expectRes, false) + + // construct block with tx const tx = Transaction.fromTxData({ gasLimit: 53000 }, { freeze: false }) tx.getSenderAddress = () => { return address } + const block = Block.fromBlockData() + block.transactions[0] = tx - const { amountSpent } = await vm.runTx({ tx }) + const result = await vm.runBlock({ block, generate: true, skipBlockValidation: true }) + const { amountSpent } = result.results[0] // verify balance is genesis amount minus amountSpent - const genesisBalance = new BN(toBuffer('0x15ac56edc4d12c0000')) const expectedNewBalance = genesisBalance.sub(amountSpent) - const req = params(method, [address.toString(), 'latest']) - const expectRes = (res: any) => { - const msg = 'should return the correct balance' - const resultBN = new BN(toBuffer(res.body.result)) - if (resultBN.eq(expectedNewBalance)) { - t.pass(msg) - } else { - throw new Error(msg) - } + req = params(method, [address.toString(), 'latest']) + expectRes = (res: any) => { + const msg = 'should return the correct balance after a tx' + t.equal(res.body.result, bnToHex(expectedNewBalance), msg) } + await baseRequest(t, server, req, 200, expectRes, false) + + // verify we can query with "earliest" + req = params(method, [address.toString(), 'earliest']) + expectRes = (res: any) => { + const msg = "should return the correct balance with 'earliest'" + t.equal(res.body.result, bnToHex(genesisBalance), msg) + } + await baseRequest(t, server, req, 200, expectRes, false) + + // verify we can query with a past block number + req = params(method, [address.toString(), '0x0']) + expectRes = (res: any) => { + const msg = 'should return the correct balance with a past block number' + t.equal(res.body.result, bnToHex(genesisBalance), msg) + } + await baseRequest(t, server, req, 200, expectRes, false) + + // call with height that exceeds chain height + req = params(method, [address.toString(), '0x1']) + expectRes = checkError(t, INVALID_PARAMS, 'specified block greater than current height') await baseRequest(t, server, req, 200, expectRes) }) @@ -85,17 +85,7 @@ tape(`${method}: call with unsupported block argument`, async (t) => { const manager = createManager(client) const server = startRPC(manager.getMethods()) - const service = client.services.find((s) => s.name === 'eth') - const vm = (service!.synchronizer as FullSynchronizer).execution.vm - - // since synchronizer.run() is not executed in the mock setup, - // manually run stateManager.generateCanonicalGenesis() - await vm.stateManager.generateCanonicalGenesis() - - // genesis address with balance - const address = Address.fromString('0xccfd725760a68823ff1e062f4cc97e1360e8d997') - - const req = params(method, [address.toString(), 'pending']) - const expectRes = checkError(t, INVALID_PARAMS, 'Currently only "latest" block supported') + const req = params(method, ['0xccfd725760a68823ff1e062f4cc97e1360e8d997', 'pending']) + const expectRes = checkError(t, INVALID_PARAMS, '"pending" is not yet supported') await baseRequest(t, server, req, 200, expectRes) }) diff --git a/packages/client/test/rpc/eth/getBlockByNumber.spec.ts b/packages/client/test/rpc/eth/getBlockByNumber.spec.ts index fa90055897..6e3ae11803 100644 --- a/packages/client/test/rpc/eth/getBlockByNumber.spec.ts +++ b/packages/client/test/rpc/eth/getBlockByNumber.spec.ts @@ -63,11 +63,7 @@ tape(`${method}: call with valid arguments`, async (t) => { const req = params(method, ['0x0', false]) const expectRes = (res: any) => { const msg = 'should return a valid block' - if (res.body.result.number === '0x0') { - t.pass(msg) - } else { - throw new Error(msg) - } + t.equal(res.body.result.number, '0x0', msg) } await baseRequest(t, server, req, 200, expectRes) }) @@ -79,17 +75,9 @@ tape(`${method}: call with false for second argument`, async (t) => { const req = params(method, ['0x0', false]) const expectRes = (res: any) => { let msg = 'should return a valid block' - if (res.body.result.number === '0x0') { - t.pass(msg) - } else { - throw new Error(msg) - } + t.equal(res.body.result.number, '0x0', msg) msg = 'should return only the hashes of the transactions' - if (typeof res.body.result.transactions[0] !== 'string') { - throw new Error(msg) - } else { - t.pass(msg) - } + t.equal(typeof res.body.result.transactions[0], 'string', msg) } await baseRequest(t, server, req, 200, expectRes) }) @@ -101,11 +89,7 @@ tape(`${method}: call with earliest param`, async (t) => { const req = params(method, ['earliest', false]) const expectRes = (res: any) => { const msg = 'should return the genesis block number' - if (res.body.result.number === '0x0') { - t.pass(msg) - } else { - throw new Error(msg) - } + t.equal(res.body.result.number, '0x0', msg) } await baseRequest(t, server, req, 200, expectRes) }) @@ -117,11 +101,7 @@ tape(`${method}: call with latest param`, async (t) => { const req = params(method, ['latest', false]) const expectRes = (res: any) => { const msg = 'should return a block number' - if (res.body.result.number === '0x1') { - t.pass(msg) - } else { - throw new Error(msg) - } + t.equal(res.body.result.number, '0x1', msg) } await baseRequest(t, server, req, 200, expectRes) }) diff --git a/packages/client/test/rpc/eth/getCode.spec.ts b/packages/client/test/rpc/eth/getCode.spec.ts index e6b2b7204f..e9d774d784 100644 --- a/packages/client/test/rpc/eth/getCode.spec.ts +++ b/packages/client/test/rpc/eth/getCode.spec.ts @@ -1,7 +1,8 @@ import tape from 'tape' -import { Address, BN } from 'ethereumjs-util' +import { Block } from '@ethereumjs/block' import Blockchain from '@ethereumjs/blockchain' import { Transaction } from '@ethereumjs/tx' +import { Address, BN } from 'ethereumjs-util' import { FullSynchronizer } from '../../../lib/sync' import { INVALID_PARAMS } from '../../../lib/rpc/error-code' import { startRPC, createManager, createClient, params, baseRequest } from '../helpers' @@ -16,6 +17,10 @@ tape(`${method}: call with valid arguments`, async (t) => { const manager = createManager(client) const server = startRPC(manager.getMethods()) + const service = client.services.find((s) => s.name === 'eth') + const { vm } = (service!.synchronizer as FullSynchronizer).execution + await vm.stateManager.generateCanonicalGenesis() + // genesis address const address = Address.fromString('0xccfd725760a68823ff1e062f4cc97e1360e8d997') @@ -23,24 +28,20 @@ tape(`${method}: call with valid arguments`, async (t) => { const req = params(method, [address.toString(), 'latest']) const expectRes = (res: any) => { const msg = 'should return the correct code' - if (res.body.result === '0x') { - t.pass(msg) - } else { - throw new Error(msg) - } + t.equal(res.body.result, '0x', msg) } await baseRequest(t, server, req, 200, expectRes) }) tape(`${method}: ensure returns correct code`, async (t) => { - const blockchain = await Blockchain.create() + const blockchain = await Blockchain.create({ validateBlocks: false, validateConsensus: false }) const client = createClient({ blockchain, includeVM: true }) const manager = createManager(client) const server = startRPC(manager.getMethods()) const service = client.services.find((s) => s.name === 'eth') - const vm = (service!.synchronizer as FullSynchronizer).execution.vm + const { vm } = (service!.synchronizer as FullSynchronizer).execution // genesis address with balance const address = Address.fromString('0xccfd725760a68823ff1e062f4cc97e1360e8d997') @@ -51,17 +52,35 @@ tape(`${method}: ensure returns correct code`, async (t) => { const code = '0x6080604052600436106039576000357c010000000000000000000000000000000000000000000000000000000090048063a2a9679914603e575b600080fd5b348015604957600080fd5b5060506066565b6040518082815260200191505060405180910390f35b6000548156fea165627a7a72305820fe2ba3506418c87a075f8f3ae19bc636bd4c18ebde0644bcb45199379603a72c0029' - // construct tx - const tx = Transaction.fromTxData({ gasLimit: 2000000, data }, { freeze: false }) + // construct block with tx + const gasLimit = 2000000 + const tx = Transaction.fromTxData({ gasLimit, data }, { freeze: false }) tx.getSenderAddress = () => { return address } + const parent = await blockchain.getLatestHeader() + const block = Block.fromBlockData( + { + header: { + parentHash: parent.hash(), + number: 1, + gasLimit, + }, + }, + { calcDifficultyFromHeader: parent } + ) + block.transactions[0] = tx - const { createdAddress } = await vm.runTx({ tx }) + // deploy contract + let ranBlock: Block | undefined = undefined + vm.once('afterBlock', (result: any) => (ranBlock = result.block)) + const result = await vm.runBlock({ block, generate: true, skipBlockValidation: true }) + const { createdAddress } = result.results[0] + await vm.blockchain.putBlock(ranBlock!) const expectedContractAddress = Address.generate(address, new BN(0)) t.ok( - createdAddress?.equals(expectedContractAddress), + createdAddress!.equals(expectedContractAddress), 'should match the expected contract address' ) @@ -69,11 +88,7 @@ tape(`${method}: ensure returns correct code`, async (t) => { const req = params(method, [expectedContractAddress.toString(), 'latest']) const expectRes = (res: any) => { const msg = 'should return the correct code' - if (res.body.result === code) { - t.pass(msg) - } else { - throw new Error(msg) - } + t.equal(res.body.result, code, msg) } await baseRequest(t, server, req, 200, expectRes) }) @@ -85,10 +100,7 @@ tape(`${method}: call with unsupported block argument`, async (t) => { const manager = createManager(client) const server = startRPC(manager.getMethods()) - // genesis address with balance - const address = Address.fromString('0xccfd725760a68823ff1e062f4cc97e1360e8d997') - - const req = params(method, [address.toString(), 'pending']) - const expectRes = checkError(t, INVALID_PARAMS, 'Currently only "latest" block supported') + const req = params(method, ['0xccfd725760a68823ff1e062f4cc97e1360e8d997', 'pending']) + const expectRes = checkError(t, INVALID_PARAMS, '"pending" is not yet supported') await baseRequest(t, server, req, 200, expectRes) }) diff --git a/packages/client/test/rpc/eth/getStorageAt.spec.ts b/packages/client/test/rpc/eth/getStorageAt.spec.ts index 4f2278ca1a..1fe7ed916e 100644 --- a/packages/client/test/rpc/eth/getStorageAt.spec.ts +++ b/packages/client/test/rpc/eth/getStorageAt.spec.ts @@ -1,7 +1,8 @@ import tape from 'tape' -import { Address, BN, keccak } from 'ethereumjs-util' +import { Block } from '@ethereumjs/block' import Blockchain from '@ethereumjs/blockchain' import { Transaction } from '@ethereumjs/tx' +import { Address, BN, bnToHex, bufferToHex, keccak } from 'ethereumjs-util' import { FullSynchronizer } from '../../../lib/sync' import { INVALID_PARAMS } from '../../../lib/rpc/error-code' import { startRPC, createManager, createClient, params, baseRequest } from '../helpers' @@ -9,45 +10,62 @@ import { checkError } from '../util' const method = 'eth_getStorageAt' -const setup = async () => { - const blockchain = await Blockchain.create() +tape(`${method}: call with valid arguments`, async (t) => { + const blockchain = await Blockchain.create({ validateBlocks: false, validateConsensus: false }) const client = createClient({ blockchain, includeVM: true }) const manager = createManager(client) const server = startRPC(manager.getMethods()) const service = client.services.find((s) => s.name === 'eth') - const vm = (service!.synchronizer as FullSynchronizer).execution.vm + const { vm } = (service!.synchronizer as FullSynchronizer).execution // genesis address with balance const address = Address.fromString('0xccfd725760a68823ff1e062f4cc97e1360e8d997') // contract inspired from https://eth.wiki/json-rpc/API#example-14 /* - // SPDX-License-Identifier: MIT - pragma solidity ^0.7.4; - - contract Storage { - uint pos0; - mapping(address => uint) pos1; - - function store() public { - pos0 = 1234; - pos1[msg.sender] = 5678; - } + // SPDX-License-Identifier: MIT + pragma solidity ^0.7.4; + + contract Storage { + uint pos0; + mapping(address => uint) pos1; + + function store() public { + pos0 = 1234; + pos1[msg.sender] = 5678; } - */ + } + */ const data = '0x6080604052348015600f57600080fd5b5060bc8061001e6000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c8063975057e714602d575b600080fd5b60336035565b005b6104d260008190555061162e600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555056fea2646970667358221220b16fe0abdbdcae31fa05c5717ebc442024b20fb637907d1a05547ea2d8ec8e5964736f6c63430007060033' - // construct tx - const tx = Transaction.fromTxData({ gasLimit: 2000000, data }, { freeze: false }) + // construct block with tx + const gasLimit = 2000000 + const tx = Transaction.fromTxData({ gasLimit, data }, { freeze: false }) tx.getSenderAddress = () => { return address } + const parent = await blockchain.getLatestHeader() + const block = Block.fromBlockData( + { + header: { + parentHash: parent.hash(), + number: 1, + gasLimit, + }, + }, + { calcDifficultyFromHeader: parent } + ) + block.transactions[0] = tx // deploy contract - const { createdAddress } = await vm.runTx({ tx }) + let ranBlock: Block | undefined = undefined + vm.once('afterBlock', (result: any) => (ranBlock = result.block)) + const result = await vm.runBlock({ block, generate: true, skipBlockValidation: true }) + const { createdAddress } = result.results[0] + await vm.blockchain.putBlock(ranBlock!) // call store() method const funcHash = '975057e7' // store() @@ -55,40 +73,42 @@ const setup = async () => { to: createdAddress!.toString(), from: address.toString(), data: `0x${funcHash}`, - gasLimit: `0x${new BN(530000).toString(16)}`, + gasLimit: bnToHex(new BN(530000)), + nonce: 1, } const storeTx = Transaction.fromTxData(storeTxData, { freeze: false }) storeTx.getSenderAddress = () => { return address } - await vm.runTx({ - tx: storeTx, - skipNonce: true, - skipBalance: true, - skipBlockGasLimitValidation: true, - }) - - return { server, createdAddress: createdAddress! } -} + const block2 = Block.fromBlockData( + { + header: { + parentHash: ranBlock!.hash(), + number: 2, + gasLimit, + }, + }, + { calcDifficultyFromHeader: block.header } + ) + block2.transactions[0] = storeTx -tape(`${method}: call with valid arguments (retrieve pos0)`, async (t) => { - const { server, createdAddress } = await setup() + // run block + let ranBlock2: Block | undefined = undefined + vm.once('afterBlock', (result: any) => (ranBlock2 = result.block)) + await vm.runBlock({ block: block2, generate: true, skipBlockValidation: true }) + await vm.blockchain.putBlock(ranBlock2!) // verify storage of pos0 is accurate - const req = params(method, [createdAddress!.toString(), '0x0', 'latest']) - const expectRes = (res: any) => { - const msg = 'should return the correct storage value' - if (res.body.result === '0x00000000000000000000000000000000000000000000000000000000000004d2') { - t.pass(msg) - } else { - throw new Error(msg) - } + let req = params(method, [createdAddress!.toString(), '0x0', 'latest']) + let expectRes = (res: any) => { + const msg = 'should return the correct storage value (pos0)' + t.equal( + res.body.result, + '0x00000000000000000000000000000000000000000000000000000000000004d2', + msg + ) } - await baseRequest(t, server, req, 200, expectRes) -}) - -tape(`${method}: call with valid arguments (retrieve pos1)`, async (t) => { - const { server, createdAddress } = await setup() + await baseRequest(t, server, req, 200, expectRes, false) // verify storage of pos1 is accurate // pos1["0xccfd725760a68823ff1e062f4cc97e1360e8d997"] @@ -99,22 +119,19 @@ tape(`${method}: call with valid arguments (retrieve pos1)`, async (t) => { 'hex' ) ) - const req = params(method, [createdAddress!.toString(), `0x${key.toString('hex')}`, 'latest']) - const expectRes = (res: any) => { - const msg = 'should return the correct storage value' - if (res.body.result === '0x000000000000000000000000000000000000000000000000000000000000162e') { - t.pass(msg) - } else { - throw new Error(msg) - } + req = params(method, [createdAddress!.toString(), bufferToHex(key), 'latest']) + expectRes = (res: any) => { + const msg = 'should return the correct storage value (pos1)' + t.equal( + res.body.result, + '0x000000000000000000000000000000000000000000000000000000000000162e', + msg + ) } - await baseRequest(t, server, req, 200, expectRes) -}) - -tape(`${method}: call with unsupported block argument`, async (t) => { - const { server, createdAddress } = await setup() + await baseRequest(t, server, req, 200, expectRes, false) - const req = params(method, [createdAddress!.toString(), '0x0', 'pending']) - const expectRes = checkError(t, INVALID_PARAMS, 'Currently only "latest" block supported') + // call with unsupported block argument + req = params(method, [createdAddress!.toString(), '0x0', 'pending']) + expectRes = checkError(t, INVALID_PARAMS, '"pending" is not yet supported') await baseRequest(t, server, req, 200, expectRes) }) diff --git a/packages/client/test/rpc/eth/getTransactionCount.spec.ts b/packages/client/test/rpc/eth/getTransactionCount.spec.ts index f862f9db4e..b1b3142559 100644 --- a/packages/client/test/rpc/eth/getTransactionCount.spec.ts +++ b/packages/client/test/rpc/eth/getTransactionCount.spec.ts @@ -1,7 +1,8 @@ import tape from 'tape' -import { Address } from 'ethereumjs-util' +import { Block } from '@ethereumjs/block' import Blockchain from '@ethereumjs/blockchain' import { Transaction } from '@ethereumjs/tx' +import { Address } from 'ethereumjs-util' import { FullSynchronizer } from '../../../lib/sync' import { INVALID_PARAMS } from '../../../lib/rpc/error-code' import { startRPC, createManager, createClient, params, baseRequest } from '../helpers' @@ -10,57 +11,58 @@ import { checkError } from '../util' const method = 'eth_getTransactionCount' tape(`${method}: call with valid arguments`, async (t) => { - const blockchain = await Blockchain.create() - - const manager = createManager(createClient({ blockchain, includeVM: true })) - const server = startRPC(manager.getMethods()) - - // a genesis address - const address = Address.fromString('0xccfd725760a68823ff1e062f4cc97e1360e8d997') - - // verify nonce is 0 - const req = params(method, [address.toString(), 'latest']) - const expectRes = (res: any) => { - const msg = 'should return the correct nonce (0)' - if (res.body.result === '0x0') { - t.pass(msg) - } else { - throw new Error(msg) - } - } - await baseRequest(t, server, req, 200, expectRes) -}) - -tape(`${method}: ensure count increments after a tx`, async (t) => { - const blockchain = await Blockchain.create() + const blockchain = await Blockchain.create({ validateBlocks: false, validateConsensus: false }) const client = createClient({ blockchain, includeVM: true }) const manager = createManager(client) const server = startRPC(manager.getMethods()) const service = client.services.find((s) => s.name === 'eth') - const vm = (service!.synchronizer as FullSynchronizer).execution.vm + const { vm } = (service!.synchronizer as FullSynchronizer).execution + + // since synchronizer.run() is not executed in the mock setup, + // manually run stateManager.generateCanonicalGenesis() + await vm.stateManager.generateCanonicalGenesis() // a genesis address const address = Address.fromString('0xccfd725760a68823ff1e062f4cc97e1360e8d997') - // construct tx + // verify nonce is 0 + let req = params(method, [address.toString(), 'latest']) + let expectRes = (res: any) => { + const msg = 'should return the correct nonce (0)' + t.equal(res.body.result, '0x0', msg) + } + await baseRequest(t, server, req, 200, expectRes, false) + + // construct block with tx const tx = Transaction.fromTxData({ gasLimit: 53000 }, { freeze: false }) tx.getSenderAddress = () => { return address } - - await vm.runTx({ tx }) - - // verify nonce is incremented to 1 - const req = params(method, [address.toString(), 'latest']) - const expectRes = (res: any) => { + const parent = await blockchain.getLatestHeader() + const block = Block.fromBlockData( + { + header: { + parentHash: parent.hash(), + number: 1, + gasLimit: 2000000, + }, + }, + { calcDifficultyFromHeader: parent } + ) + block.transactions[0] = tx + + let ranBlock: Block | undefined = undefined + vm.once('afterBlock', (result: any) => (ranBlock = result.block)) + await vm.runBlock({ block, generate: true, skipBlockValidation: true }) + await vm.blockchain.putBlock(ranBlock!) + + // verify nonce increments after a tx + req = params(method, [address.toString(), 'latest']) + expectRes = (res: any) => { const msg = 'should return the correct nonce (1)' - if (res.body.result === '0x1') { - t.pass(msg) - } else { - throw new Error(msg) - } + t.equal(res.body.result, '0x1', msg) } await baseRequest(t, server, req, 200, expectRes) }) @@ -72,10 +74,7 @@ tape(`${method}: call with unsupported block argument`, async (t) => { const manager = createManager(client) const server = startRPC(manager.getMethods()) - // genesis address with balance - const address = Address.fromString('0xccfd725760a68823ff1e062f4cc97e1360e8d997') - - const req = params(method, [address.toString(), 'pending']) - const expectRes = checkError(t, INVALID_PARAMS, 'Currently only "latest" block supported') + const req = params(method, ['0xccfd725760a68823ff1e062f4cc97e1360e8d997', 'pending']) + const expectRes = checkError(t, INVALID_PARAMS, '"pending" is not yet supported') await baseRequest(t, server, req, 200, expectRes) }) From 4af298d6f77da572d6d946fa84e786153ec747c6 Mon Sep 17 00:00:00 2001 From: Ryan Ghods Date: Tue, 7 Dec 2021 16:46:28 -1000 Subject: [PATCH 2/3] client rpc: simplify result comparisons --- packages/client/test/rpc/eth/chainId.spec.ts | 6 +- .../getBlockTransactionCountByHash.spec.ts | 6 +- packages/client/test/rpc/eth/getLogs.spec.ts | 58 ++++--------------- .../test/rpc/eth/getTransactionByHash.spec.ts | 30 ++-------- .../rpc/eth/getTransactionReceipt.spec.ts | 18 +----- .../eth/getUncleCountByBlockNumber.spec.ts | 6 +- .../test/rpc/eth/protocolVersion.spec.ts | 6 +- packages/client/test/rpc/eth/syncing.spec.ts | 8 +-- .../client/test/rpc/net/listening.spec.ts | 26 ++------- .../client/test/rpc/net/peerCount.spec.ts | 6 +- packages/client/test/rpc/net/version.spec.ts | 20 +------ .../test/rpc/web3/clientVersion.spec.ts | 32 ++-------- packages/client/test/rpc/web3/sha3.spec.ts | 24 ++------ 13 files changed, 42 insertions(+), 204 deletions(-) diff --git a/packages/client/test/rpc/eth/chainId.spec.ts b/packages/client/test/rpc/eth/chainId.spec.ts index d2d73f0d19..19b5e54ace 100644 --- a/packages/client/test/rpc/eth/chainId.spec.ts +++ b/packages/client/test/rpc/eth/chainId.spec.ts @@ -11,11 +11,7 @@ tape(`${method}: calls`, async (t) => { const req = params(method, []) const expectRes = (res: any) => { const msg = 'chainId should be a string' - if (typeof res.body.result !== 'string') { - throw new Error(msg) - } else { - t.pass(msg) - } + t.equal(typeof res.body.result, 'string', msg) } await baseRequest(t, server, req, 200, expectRes) }) diff --git a/packages/client/test/rpc/eth/getBlockTransactionCountByHash.spec.ts b/packages/client/test/rpc/eth/getBlockTransactionCountByHash.spec.ts index 06ae514d5b..822f3ee1d3 100644 --- a/packages/client/test/rpc/eth/getBlockTransactionCountByHash.spec.ts +++ b/packages/client/test/rpc/eth/getBlockTransactionCountByHash.spec.ts @@ -11,11 +11,7 @@ tape(`${method}: call with valid arguments`, async (t) => { const req = params(method, ['0x910abca1728c53e8d6df870dd7af5352e974357dc58205dea1676be17ba6becf']) const expectRes = (res: any) => { const msg = 'transaction count should be 1' - if (res.body.result !== `0x1`) { - throw new Error(msg) - } else { - t.pass(msg) - } + t.equal(res.body.result, '0x1', msg) } await baseRequest(t, server, req, 200, expectRes) }) diff --git a/packages/client/test/rpc/eth/getLogs.spec.ts b/packages/client/test/rpc/eth/getLogs.spec.ts index 051344b38e..5328f5c00b 100644 --- a/packages/client/test/rpc/eth/getLogs.spec.ts +++ b/packages/client/test/rpc/eth/getLogs.spec.ts @@ -97,7 +97,7 @@ tape(`${method}: call with valid arguments`, async (t) => { ) { t.pass(msg) } else { - throw new Error(msg) + t.fail(msg) } } await baseRequest(t, server, req, 200, expectRes, false) @@ -106,11 +106,7 @@ tape(`${method}: call with valid arguments`, async (t) => { req = params(method, [{ fromBlock: '0x0', toBlock: '0x1' }]) expectRes = (res: any) => { const msg = 'should return the correct logs (fromBlock/toBlock as block numbers)' - if (res.body.result.length === 20) { - t.pass(msg) - } else { - throw new Error(msg) - } + t.equal(res.body.result.length, 20, msg) } await baseRequest(t, server, req, 200, expectRes, false) @@ -121,7 +117,7 @@ tape(`${method}: call with valid arguments`, async (t) => { if (res.body.result.length === 10 && res.body.result[0].address === contractAddr1.toString()) { t.pass(msg) } else { - throw new Error(msg) + t.fail(msg) } } await baseRequest(t, server, req, 200, expectRes, false) @@ -130,11 +126,7 @@ tape(`${method}: call with valid arguments`, async (t) => { req = params(method, [{ topics: [] }]) expectRes = (res: any) => { const msg = 'should return the correct logs (filter by topic - empty means anything)' - if (res.body.result.length === 20) { - t.pass(msg) - } else { - throw new Error(msg) - } + t.equal(res.body.result.length, 20, msg) } await baseRequest(t, server, req, 200, expectRes, false) @@ -144,11 +136,7 @@ tape(`${method}: call with valid arguments`, async (t) => { ]) expectRes = (res: any) => { const msg = 'should return the correct logs (filter by topic - exact match)' - if (res.body.result.length === 20) { - t.pass(msg) - } else { - throw new Error(msg) - } + t.equal(res.body.result.length, 20, msg) } await baseRequest(t, server, req, 200, expectRes, false) @@ -158,11 +146,7 @@ tape(`${method}: call with valid arguments`, async (t) => { ]) expectRes = (res: any) => { const msg = 'should return the correct logs (filter by topic - exact match for second topic)' - if (res.body.result.length === 20) { - t.pass(msg) - } else { - throw new Error(msg) - } + t.equal(res.body.result.length, 20, msg) } await baseRequest(t, server, req, 200, expectRes, false) @@ -181,11 +165,7 @@ tape(`${method}: call with valid arguments`, async (t) => { ]) expectRes = (res: any) => { const msg = 'should return the correct logs (filter by topic - A or B in first position)' - if (res.body.result.length === 20) { - t.pass(msg) - } else { - throw new Error(msg) - } + t.equal(res.body.result.length, 20, msg) } await baseRequest(t, server, req, 200, expectRes, false) @@ -197,11 +177,7 @@ tape(`${method}: call with valid arguments`, async (t) => { ]) expectRes = (res: any) => { const msg = 'should return the correct logs (filter by topic - null means anything)' - if (res.body.result.length === 20) { - t.pass(msg) - } else { - throw new Error(msg) - } + t.equal(res.body.result.length, 20, msg) } await baseRequest(t, server, req, 200, expectRes, false) @@ -214,11 +190,7 @@ tape(`${method}: call with valid arguments`, async (t) => { ]) expectRes = (res: any) => { const msg = 'should return the correct logs (filter by blockHash)' - if (res.body.result.length === 20) { - t.pass(msg) - } else { - throw new Error(msg) - } + t.equal(res.body.result.length, 20, msg) } await baseRequest(t, server, req, 200, expectRes, true) // pass endOnFinish=true for last test }) @@ -273,11 +245,7 @@ tape(`${method}: call with invalid params`, async (t) => { req = params(method, [{ address: '0x0000000000000000000000000000000000000001' }]) expectRes = (res: any) => { const msg = 'should return empty logs' - if (res.body.result.length === 0) { - t.pass(msg) - } else { - throw new Error(msg) - } + t.equal(res.body.result.length, 0, msg) } await baseRequest(t, server, req, 200, expectRes, false) @@ -285,11 +253,7 @@ tape(`${method}: call with invalid params`, async (t) => { req = params(method, [{ topics: ['0x1234'] }]) expectRes = (res: any) => { const msg = 'should return empty logs' - if (res.body.result.length === 0) { - t.pass(msg) - } else { - throw new Error(msg) - } + t.equal(res.body.result.length, 0, msg) } await baseRequest(t, server, req, 200, expectRes, true) // pass endOnFinish=true for last test }) diff --git a/packages/client/test/rpc/eth/getTransactionByHash.spec.ts b/packages/client/test/rpc/eth/getTransactionByHash.spec.ts index b4a0b4e9b6..b8f804a5ee 100644 --- a/packages/client/test/rpc/eth/getTransactionByHash.spec.ts +++ b/packages/client/test/rpc/eth/getTransactionByHash.spec.ts @@ -28,11 +28,7 @@ tape(`${method}: call with legacy tx`, async (t) => { let req = params(method, [bufferToHex(tx.hash())]) let expectRes = (res: any) => { const msg = 'should return the correct tx' - if (res.body.result.hash === bufferToHex(tx.hash())) { - t.pass(msg) - } else { - throw new Error(msg) - } + t.equal(res.body.result.hash, bufferToHex(tx.hash()), msg) } await baseRequest(t, server, req, 200, expectRes, false) @@ -41,11 +37,7 @@ tape(`${method}: call with legacy tx`, async (t) => { req = params(method, [bufferToHex(tx.hash())]) expectRes = (res: any) => { const msg = 'should return null when past txLookupLimit' - if (res.body.result === null) { - t.pass(msg) - } else { - throw new Error(msg) - } + t.equal(res.body.result, null, msg) } await baseRequest(t, server, req, 200, expectRes, true) // pass endOnFinish=true for last test }) @@ -74,11 +66,7 @@ tape(`${method}: call with 1559 tx`, async (t) => { let req = params(method, [bufferToHex(tx.hash())]) let expectRes = (res: any) => { const msg = 'should return the correct tx type' - if (res.body.result.type === '0x2') { - t.pass(msg) - } else { - throw new Error(msg) - } + t.equal(res.body.result.type, '0x2', msg) } await baseRequest(t, server, req, 200, expectRes, false) @@ -89,11 +77,7 @@ tape(`${method}: call with 1559 tx`, async (t) => { req = params(method, [bufferToHex(tx.hash())]) expectRes = (res: any) => { const msg = 'should return the correct tx when txLookupLimit=0' - if (res.body.result.hash === bufferToHex(tx.hash())) { - t.pass(msg) - } else { - throw new Error(msg) - } + t.equal(res.body.result.hash, bufferToHex(tx.hash()), msg) } await baseRequest(t, server, req, 200, expectRes, true) // pass endOnFinish=true for last test }) @@ -105,11 +89,7 @@ tape(`${method}: call with unknown tx hash`, async (t) => { const req = params(method, ['0x89ea5b54111befb936851660a72b686a21bc2fc4889a9a308196ff99d08925a0']) const expectRes = (res: any) => { const msg = 'should return null' - if (res.body.result === null) { - t.pass(msg) - } else { - throw new Error(msg) - } + t.equal(res.body.result, null, msg) } await baseRequest(t, server, req, 200, expectRes) }) diff --git a/packages/client/test/rpc/eth/getTransactionReceipt.spec.ts b/packages/client/test/rpc/eth/getTransactionReceipt.spec.ts index d0dedceec3..358e9f17a9 100644 --- a/packages/client/test/rpc/eth/getTransactionReceipt.spec.ts +++ b/packages/client/test/rpc/eth/getTransactionReceipt.spec.ts @@ -28,11 +28,7 @@ tape(`${method}: call with legacy tx`, async (t) => { const req = params(method, [bufferToHex(tx.hash())]) const expectRes = (res: any) => { const msg = 'should return the correct tx' - if (res.body.result.transactionHash === bufferToHex(tx.hash())) { - t.pass(msg) - } else { - throw new Error(msg) - } + t.equal(res.body.result.transactionHash, bufferToHex(tx.hash()), msg) } await baseRequest(t, server, req, 200, expectRes) }) @@ -60,11 +56,7 @@ tape(`${method}: call with 1559 tx`, async (t) => { const req = params(method, [bufferToHex(tx.hash())]) const expectRes = (res: any) => { const msg = 'should return the correct tx' - if (res.body.result.transactionHash === bufferToHex(tx.hash())) { - t.pass(msg) - } else { - throw new Error(msg) - } + t.equal(res.body.result.transactionHash, bufferToHex(tx.hash()), msg) } await baseRequest(t, server, req, 200, expectRes) }) @@ -76,11 +68,7 @@ tape(`${method}: call with unknown tx hash`, async (t) => { const req = params(method, ['0x89ea5b54111befb936851660a72b686a21bc2fc4889a9a308196ff99d08925a0']) const expectRes = (res: any) => { const msg = 'should return null' - if (res.body.result === null) { - t.pass(msg) - } else { - throw new Error(msg) - } + t.equal(res.body.result, null, msg) } await baseRequest(t, server, req, 200, expectRes) }) diff --git a/packages/client/test/rpc/eth/getUncleCountByBlockNumber.spec.ts b/packages/client/test/rpc/eth/getUncleCountByBlockNumber.spec.ts index 08a4104310..f1c74a7a05 100644 --- a/packages/client/test/rpc/eth/getUncleCountByBlockNumber.spec.ts +++ b/packages/client/test/rpc/eth/getUncleCountByBlockNumber.spec.ts @@ -30,11 +30,7 @@ tape(`${method}: call with valid arguments`, async (t) => { const req = params(method, ['0x1']) const expectRes = (res: any) => { const msg = 'should return the correct number' - if (res.body.result !== mockUncleCount) { - throw new Error(msg) - } else { - t.pass(msg) - } + t.equal(res.body.result, mockUncleCount, msg) } await baseRequest(t, server, req, 200, expectRes) }) diff --git a/packages/client/test/rpc/eth/protocolVersion.spec.ts b/packages/client/test/rpc/eth/protocolVersion.spec.ts index 7eba122ddb..cf70263a18 100644 --- a/packages/client/test/rpc/eth/protocolVersion.spec.ts +++ b/packages/client/test/rpc/eth/protocolVersion.spec.ts @@ -10,11 +10,7 @@ tape(`${method}: call`, async (t) => { const expectRes = (res: any) => { const responseBlob = res.body const msg = 'protocol version should be a string' - if (typeof responseBlob.result !== 'string') { - throw new Error(msg) - } else { - t.pass(msg) - } + t.equal(typeof responseBlob.result, 'string', msg) } await baseRequest(t, server, req, 200, expectRes) }) diff --git a/packages/client/test/rpc/eth/syncing.spec.ts b/packages/client/test/rpc/eth/syncing.spec.ts index fcac4f4905..e074102755 100644 --- a/packages/client/test/rpc/eth/syncing.spec.ts +++ b/packages/client/test/rpc/eth/syncing.spec.ts @@ -20,11 +20,7 @@ tape(`${method}: should return false when the client is synchronized`, async (t) const req = params(method, []) const expectRes = (res: any) => { const msg = 'should return false' - if (res.body.result === false) { - t.pass(msg) - } else { - throw new Error(msg) - } + t.equal(res.body.result, false, msg) } await baseRequest(t, server, req, 200, expectRes) }) @@ -85,7 +81,7 @@ tape(`${method}: should return syncing status object when unsynced`, async (t) = ) { t.pass(msg) } else { - throw new Error(msg) + t.fail(msg) } } diff --git a/packages/client/test/rpc/net/listening.spec.ts b/packages/client/test/rpc/net/listening.spec.ts index a875d81203..aa085da933 100644 --- a/packages/client/test/rpc/net/listening.spec.ts +++ b/packages/client/test/rpc/net/listening.spec.ts @@ -11,18 +11,9 @@ tape(`${method}: call while listening`, async (t) => { const expectRes = (res: any) => { const { result } = res.body let msg = 'result should be a boolean' - if (typeof result !== 'boolean') { - throw new Error(msg) - } else { - t.pass(msg) - } - + t.equal(typeof result, 'boolean', msg) msg = 'should be listening' - if (result !== true) { - throw new Error(msg) - } else { - t.pass(msg) - } + t.equal(result, true, msg) } await baseRequest(t, server, req, 200, expectRes) }) @@ -35,18 +26,9 @@ tape(`${method}: call while not listening`, async (t) => { const expectRes = (res: any) => { const { result } = res.body let msg = 'result should be a boolean' - if (typeof result !== 'boolean') { - throw new Error(msg) - } else { - t.pass(msg) - } - + t.equal(typeof result, 'boolean', msg) msg = 'should not be listening' - if (result !== false) { - throw new Error(msg) - } else { - t.pass(msg) - } + t.equal(result, false, msg) } await baseRequest(t, server, req, 200, expectRes) }) diff --git a/packages/client/test/rpc/net/peerCount.spec.ts b/packages/client/test/rpc/net/peerCount.spec.ts index cb60d2312a..43486e45d3 100644 --- a/packages/client/test/rpc/net/peerCount.spec.ts +++ b/packages/client/test/rpc/net/peerCount.spec.ts @@ -11,11 +11,7 @@ tape(`${method}: call`, async (t) => { const expectRes = (res: any) => { const { result } = res.body const msg = 'result should be a hex number' - if (result.substring(0, 2) !== '0x') { - throw new Error(msg) - } else { - t.pass(msg) - } + t.equal(result.substring(0, 2), '0x', msg) } await baseRequest(t, server, req, 200, expectRes) }) diff --git a/packages/client/test/rpc/net/version.spec.ts b/packages/client/test/rpc/net/version.spec.ts index bc839be1ed..d868a81a55 100644 --- a/packages/client/test/rpc/net/version.spec.ts +++ b/packages/client/test/rpc/net/version.spec.ts @@ -6,25 +6,11 @@ const method = 'net_version' function compareResult(t: any, result: any, chainId: any) { let msg = 'result should be a string' - if (typeof result !== 'string') { - throw new Error(msg) - } else { - t.pass(msg) - } - + t.equal(typeof result, 'string', msg) msg = 'result string should not be empty' - if (result.length === 0) { - throw new Error(msg) - } else { - t.pass(msg) - } - + t.notEqual(result.length, 0, msg) msg = `should be the correct chain ID (expected: ${chainId}, received: ${result})` - if (result !== chainId) { - throw new Error(msg) - } else { - t.pass(msg) - } + t.equal(result, chainId, msg) } tape(`${method}: call on ropsten`, async (t) => { diff --git a/packages/client/test/rpc/web3/clientVersion.spec.ts b/packages/client/test/rpc/web3/clientVersion.spec.ts index 3834366a80..0bce482af2 100644 --- a/packages/client/test/rpc/web3/clientVersion.spec.ts +++ b/packages/client/test/rpc/web3/clientVersion.spec.ts @@ -17,39 +17,17 @@ tape(`${method}: call`, async (t) => { const expectedNodeVersion = `node${process.version.substring(1)}` let msg = 'result string should not be empty' - if (result.length === 0) { - throw new Error(msg) - } else { - t.pass(msg) - } - + t.notEqual(result.length, 0, msg) const [actualClientTitle, actualPackageVersion, actualPlatform, actualNodeVersion] = result.split('/') - msg = 'client title should be correct' - if (actualClientTitle !== expectedClientTitle) { - throw new Error(msg) - } else { - t.pass(msg) - } + t.equal(actualClientTitle, expectedClientTitle, msg) msg = 'package version should be correct' - if (actualPackageVersion !== expectedPackageVersion) { - throw new Error(msg) - } else { - t.pass(msg) - } + t.equal(actualPackageVersion, expectedPackageVersion, msg) msg = 'platform should be correct' - if (actualPlatform !== expectedPlatform) { - throw new Error(msg) - } else { - t.pass(msg) - } + t.equal(actualPlatform, expectedPlatform, msg) msg = 'Node.js version should be correct' - if (actualNodeVersion !== expectedNodeVersion) { - throw new Error(msg) - } else { - t.pass(msg) - } + t.equal(actualNodeVersion, expectedNodeVersion, msg) } await baseRequest(t, server, req, 200, expectRes) }) diff --git a/packages/client/test/rpc/web3/sha3.spec.ts b/packages/client/test/rpc/web3/sha3.spec.ts index da094fbc14..017ce40d47 100644 --- a/packages/client/test/rpc/web3/sha3.spec.ts +++ b/packages/client/test/rpc/web3/sha3.spec.ts @@ -5,20 +5,12 @@ const method = 'web3_sha3' function compareErrorCode(t: any, error: any, errorCode: any) { const msg = `should return the correct error code (expected: ${errorCode}, received: ${error.code})` - if (error.code !== errorCode) { - throw new Error(msg) - } else { - t.pass(msg) - } + t.equal(error.code, errorCode, msg) } function compareErrorMsg(t: any, error: any, errorMsg: any) { const msg = `should return "${errorMsg}" error message` - if (error.message !== errorMsg) { - throw new Error(msg) - } else { - t.pass(msg) - } + t.equal(error.message, errorMsg, msg) } tape(`${method}: call with one valid parameter`, async (t) => { @@ -28,18 +20,10 @@ tape(`${method}: call with one valid parameter`, async (t) => { const expectRes = (res: any) => { const { result } = res.body let msg = 'result string should not be empty' - if (result.length === 0) { - throw new Error(msg) - } else { - t.pass(msg) - } + t.notEqual(result.length, 0, msg) msg = 'should return the correct hash value' - if (result !== '0x47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad') { - throw new Error(msg) - } else { - t.pass(msg) - } + t.equal(result, '0x47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad', msg) } await baseRequest(t, server, req, 200, expectRes) }) From 81ee9e446c111a73d3be5f90a3348c90e4beb250 Mon Sep 17 00:00:00 2001 From: Ryan Ghods Date: Thu, 9 Dec 2021 18:23:26 -1000 Subject: [PATCH 3/3] add getProof --- packages/client/lib/rpc/modules/eth.ts | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/packages/client/lib/rpc/modules/eth.ts b/packages/client/lib/rpc/modules/eth.ts index 75681dfff1..eadd84a562 100644 --- a/packages/client/lib/rpc/modules/eth.ts +++ b/packages/client/lib/rpc/modules/eth.ts @@ -920,23 +920,15 @@ export class Eth { * @returns The {@link Proof} */ async getProof(params: [string, string[], string]): Promise { - const [addressHex, slotsHex, blockOption] = params + const [addressHex, slotsHex, blockOpt] = params + const block = await getBlockByOption(blockOpt, this._chain) if (!this._vm) { throw new Error('missing vm') } - // use a copy of the vm in case new blocks are executed const vm = this._vm.copy() - if (blockOption !== 'latest') { - const latest = await vm.blockchain.getLatestHeader() - if (blockOption !== bnToHex(latest.number)) { - throw { - code: INVALID_PARAMS, - message: `Currently only "latest" block supported`, - } - } - } + await vm.stateManager.setStateRoot(block.header.stateRoot) const address = Address.fromString(addressHex) const slots = slotsHex.map((slotHex) => setLengthLeft(toBuffer(slotHex), 32))