diff --git a/config/eslint.js b/config/eslint.js index b30106560c..f6fe562042 100644 --- a/config/eslint.js +++ b/config/eslint.js @@ -45,7 +45,8 @@ module.exports = { 'no-redeclare': 'off', '@typescript-eslint/no-redeclare': ['error'], '@typescript-eslint/restrict-plus-operands': 'off', - 'import/no-default-export' : ['error'] + 'import/no-default-export' : ['error'], + '@typescript-eslint/strict-boolean-expressions': ['error'] }, parserOptions: { sourceType: 'module', diff --git a/packages/block/src/block.ts b/packages/block/src/block.ts index 9dea8986a9..9264d7eefc 100644 --- a/packages/block/src/block.ts +++ b/packages/block/src/block.ts @@ -1,6 +1,6 @@ import { Trie } from '@ethereumjs/trie' import { keccak256 } from 'ethereum-cryptography/keccak' -import { arrToBufArr, bufArrToArr, KECCAK256_RLP, bufferToHex } from '@ethereumjs/util' +import { arrToBufArr, bufArrToArr, KECCAK256_RLP, bufferToHex, isTruthy } from '@ethereumjs/util' import { RLP } from 'rlp' import { Common, ConsensusType } from '@ethereumjs/common' import { @@ -98,7 +98,7 @@ export class Block { // parse transactions const transactions = [] - for (const txData of txsData || []) { + for (const txData of isTruthy(txsData) ? txsData : []) { transactions.push( TransactionFactory.fromBlockBodyData(txData, { ...opts, @@ -118,10 +118,10 @@ export class Block { // Disable this option here (all other options carried over), since this overwrites the provided Difficulty to an incorrect value calcDifficultyFromHeader: undefined, } - if (uncleOpts.hardforkByTD) { + if (isTruthy(uncleOpts.hardforkByTD)) { delete uncleOpts.hardforkByBlockNumber } - for (const uncleHeaderData of uhsData || []) { + for (const uncleHeaderData of isTruthy(uhsData) ? uhsData : []) { uncleHeaders.push(BlockHeader.fromValuesArray(uncleHeaderData, uncleOpts)) } @@ -241,7 +241,7 @@ export class Block { const errors: string[] = [] this.transactions.forEach((tx, i) => { const errs = tx.validate(true) - if (this._common.isActivatedEIP(1559)) { + if (this._common.isActivatedEIP(1559) === true) { if (tx.supports(Capability.EIP1559FeeMarket)) { tx = tx as FeeMarketEIP1559Transaction if (tx.maxFeePerGas < this.header.baseFeePerGas!) { diff --git a/packages/block/src/from-rpc.ts b/packages/block/src/from-rpc.ts index f430e446b3..f1214d9a2c 100644 --- a/packages/block/src/from-rpc.ts +++ b/packages/block/src/from-rpc.ts @@ -1,5 +1,5 @@ import { TransactionFactory, TypedTransaction, TxData } from '@ethereumjs/tx' -import { toBuffer, setLengthLeft } from '@ethereumjs/util' +import { toBuffer, setLengthLeft, isTruthy } from '@ethereumjs/util' import { Block, BlockOptions } from './index' import { numberToHex } from './helpers' @@ -16,7 +16,7 @@ function normalizeTxParams(_txParams: any) { txParams.value = numberToHex(txParams.value) // strict byte length checking - txParams.to = txParams.to ? setLengthLeft(toBuffer(txParams.to), 20) : null + txParams.to = isTruthy(txParams.to) ? setLengthLeft(toBuffer(txParams.to), 20) : null // v as raw signature value {0,1} // v is the recovery bit and can be either {0,1} or {27,28}. @@ -32,13 +32,13 @@ function normalizeTxParams(_txParams: any) { * * @param blockParams - Ethereum JSON RPC of block (eth_getBlockByNumber) * @param uncles - Optional list of Ethereum JSON RPC of uncles (eth_getUncleByBlockHashAndIndex) - * @param chainOptions - An object describing the blockchain + * @param options - An object describing the blockchain */ export function blockFromRpc(blockParams: any, uncles: any[] = [], options?: BlockOptions) { const header = blockHeaderFromRpc(blockParams, options) const transactions: TypedTransaction[] = [] - if (blockParams.transactions) { + if (isTruthy(blockParams.transactions)) { const opts = { common: header._common } for (const _txParams of blockParams.transactions) { const txParams = normalizeTxParams(_txParams) diff --git a/packages/block/src/header-from-rpc.ts b/packages/block/src/header-from-rpc.ts index 38234ada65..86c082aece 100644 --- a/packages/block/src/header-from-rpc.ts +++ b/packages/block/src/header-from-rpc.ts @@ -1,12 +1,13 @@ import { BlockHeader } from './header' import { BlockOptions } from './types' import { numberToHex } from './helpers' +import { isTruthy } from '@ethereumjs/util' /** * Creates a new block header object from Ethereum JSON RPC. * * @param blockParams - Ethereum JSON RPC of block (eth_getBlockByNumber) - * @param chainOptions - An object describing the blockchain + * @param options - An object describing the blockchain */ export function blockHeaderFromRpc(blockParams: any, options?: BlockOptions) { const { @@ -36,7 +37,7 @@ export function blockHeaderFromRpc(blockParams: any, options?: BlockOptions) { coinbase: miner, stateRoot, transactionsTrie: transactionsRoot, - receiptTrie: receiptRoot || receiptsRoot, + receiptTrie: isTruthy(receiptRoot) ? receiptRoot : receiptsRoot, logsBloom, difficulty: numberToHex(difficulty), number, diff --git a/packages/block/src/header.ts b/packages/block/src/header.ts index c51920b9eb..e01c185fd3 100644 --- a/packages/block/src/header.ts +++ b/packages/block/src/header.ts @@ -23,6 +23,8 @@ import { toType, TypeOutput, zeros, + isTruthy, + isFalsy, } from '@ethereumjs/util' import { RLP } from 'rlp' import { BlockHeaderBuffer, BlockOptions, HeaderData, JsonHeader } from './types' @@ -65,7 +67,7 @@ export class BlockHeader { * EIP-4399: After merge to PoS, `mixHash` supplanted as `prevRandao` */ get prevRandao() { - if (!this._common.isActivatedEIP(4399)) { + if (this._common.isActivatedEIP(4399) === false) { const msg = this._errorMsg( 'The prevRandao parameter can only be accessed when EIP-4399 is activated' ) @@ -87,17 +89,17 @@ export class BlockHeader { /** * Static constructor to create a block header from a RLP-serialized header * - * @param headerData + * @param serializedHeaderData * @param opts */ - public static fromRLPSerializedHeader(serialized: Buffer, opts: BlockOptions = {}) { - const values = arrToBufArr(RLP.decode(Uint8Array.from(serialized))) as Buffer[] + public static fromRLPSerializedHeader(serializedHeaderData: Buffer, opts: BlockOptions = {}) { + const values = arrToBufArr(RLP.decode(Uint8Array.from(serializedHeaderData))) if (!Array.isArray(values)) { throw new Error('Invalid serialized header input. Must be array') } - return BlockHeader.fromValuesArray(values, opts) + return BlockHeader.fromValuesArray(values as Buffer[], opts) } /** @@ -198,7 +200,7 @@ export class BlockHeader { const parentHash = toType(headerData.parentHash, TypeOutput.Buffer) ?? defaults.parentHash const uncleHash = toType(headerData.uncleHash, TypeOutput.Buffer) ?? defaults.uncleHash - const coinbase = headerData.coinbase + const coinbase = isTruthy(headerData.coinbase) ? new Address(toType(headerData.coinbase, TypeOutput.Buffer)) : defaults.coinbase const stateRoot = toType(headerData.stateRoot, TypeOutput.Buffer) ?? defaults.stateRoot @@ -222,11 +224,9 @@ export class BlockHeader { this._common.setHardforkByBlockNumber(number, options.hardforkByTD) } - if (this._common.isActivatedEIP(1559)) { + if (this._common.isActivatedEIP(1559) === true) { if (baseFeePerGas === undefined) { - const londonHfBlock = this._common.hardforkBlock(Hardfork.London) - const isInitialEIP1559Block = number === londonHfBlock - if (isInitialEIP1559Block) { + if (number === this._common.hardforkBlock(Hardfork.London)) { baseFeePerGas = this._common.param('gasConfig', 'initialBaseFee') } else { // Minimum possible value for baseFeePerGas is 7, @@ -344,14 +344,13 @@ export class BlockHeader { } // Validation for EIP-1559 blocks - if (this._common.isActivatedEIP(1559)) { + if (this._common.isActivatedEIP(1559) === true) { if (typeof this.baseFeePerGas !== 'bigint') { const msg = this._errorMsg('EIP1559 block has no base fee field') throw new Error(msg) } const londonHfBlock = this._common.hardforkBlock(Hardfork.London) - const isInitialEIP1559Block = londonHfBlock && this.number === londonHfBlock - if (isInitialEIP1559Block) { + if (isTruthy(londonHfBlock) && this.number === londonHfBlock) { const initialBaseFee = this._common.param('gasConfig', 'initialBaseFee') if (this.baseFeePerGas! !== initialBaseFee) { const msg = this._errorMsg('Initial EIP1559 block does not have initial base fee') @@ -455,7 +454,7 @@ export class BlockHeader { // EIP-1559: assume double the parent gas limit on fork block // to adopt to the new gas target centered logic const londonHardforkBlock = this._common.hardforkBlock(Hardfork.London) - if (londonHardforkBlock && this.number === londonHardforkBlock) { + if (isTruthy(londonHardforkBlock) && this.number === londonHardforkBlock) { const elasticity = this._common.param('gasConfig', 'elasticityMultiplier') parentGasLimit = parentGasLimit * elasticity } @@ -489,7 +488,7 @@ export class BlockHeader { * Calculates the base fee for a potential next block */ public calcNextBaseFee(): bigint { - if (!this._common.isActivatedEIP(1559)) { + if (this._common.isActivatedEIP(1559) === false) { const msg = this._errorMsg( 'calcNextBaseFee() can only be called with EIP1559 being activated' ) @@ -551,7 +550,7 @@ export class BlockHeader { this.nonce, ] - if (this._common.isActivatedEIP(1559)) { + if (this._common.isActivatedEIP(1559) === true) { rawItems.push(bigIntToUnpaddedBuffer(this.baseFeePerGas!)) } @@ -615,7 +614,7 @@ export class BlockHeader { // We use a ! here as TS cannot follow this hardfork-dependent logic, but it always gets assigned let dif!: bigint - if (this._common.hardforkGteHardfork(hardfork, Hardfork.Byzantium)) { + if (this._common.hardforkGteHardfork(hardfork, Hardfork.Byzantium) === true) { // max((2 if len(parent.uncles) else 1) - ((timestamp - parent.timestamp) // 9), -99) (EIP100) const uncleAddend = parentBlockHeader.uncleHash.equals(KECCAK256_RLP_ARRAY) ? 1 : 2 let a = BigInt(uncleAddend) - (blockTs - parentTs) / BigInt(9) @@ -627,13 +626,13 @@ export class BlockHeader { dif = parentDif + offset * a } - if (this._common.hardforkGteHardfork(hardfork, Hardfork.Byzantium)) { + if (this._common.hardforkGteHardfork(hardfork, Hardfork.Byzantium) === true) { // Get delay as parameter from common num = num - this._common.param('pow', 'difficultyBombDelay') if (num < BigInt(0)) { num = BigInt(0) } - } else if (this._common.hardforkGteHardfork(hardfork, Hardfork.Homestead)) { + } else if (this._common.hardforkGteHardfork(hardfork, Hardfork.Homestead) === true) { // 1 - (block_timestamp - parent_timestamp) // 10 let a = BigInt(1) - (blockTs - parentTs) / BigInt(10) const cutoff = BigInt(-99) @@ -810,7 +809,7 @@ export class BlockHeader { mixHash: '0x' + this.mixHash.toString('hex'), nonce: '0x' + this.nonce.toString('hex'), } - if (this._common.isActivatedEIP(1559)) { + if (this._common.isActivatedEIP(1559) === true) { jsonDict.baseFeePerGas = bigIntToHex(this.baseFeePerGas!) } return jsonDict @@ -821,15 +820,11 @@ export class BlockHeader { * activation block (see: https://blog.slock.it/hard-fork-specification-24b889e70703) */ private _validateDAOExtraData() { - if (!this._common.hardforkIsActiveOnBlock(Hardfork.Dao, this.number)) { + if (this._common.hardforkIsActiveOnBlock(Hardfork.Dao, this.number) === false) { return } const DAOActivationBlock = this._common.hardforkBlock(Hardfork.Dao) - if ( - !DAOActivationBlock || - DAOActivationBlock === BigInt(0) || - this.number < DAOActivationBlock - ) { + if (isFalsy(DAOActivationBlock) || this.number < DAOActivationBlock) { return } const DAO_ExtraData = Buffer.from('64616f2d686172642d666f726b', 'hex') diff --git a/packages/block/src/helpers.ts b/packages/block/src/helpers.ts index 7edc96247b..ea3093055e 100644 --- a/packages/block/src/helpers.ts +++ b/packages/block/src/helpers.ts @@ -1,11 +1,11 @@ -import { isHexString } from '@ethereumjs/util' +import { isFalsy, isHexString } from '@ethereumjs/util' /** * Returns a 0x-prefixed hex number string from a hex string or string integer. * @param {string} input string to check, convert, and return */ export const numberToHex = function (input?: string) { - if (!input) return undefined + if (isFalsy(input)) return undefined if (!isHexString(input)) { const regex = new RegExp(/^\d+$/) // test to make sure input contains only digits if (!regex.test(input)) { diff --git a/packages/block/test/block.spec.ts b/packages/block/test/block.spec.ts index c6b78d6b31..d8bc9c43a4 100644 --- a/packages/block/test/block.spec.ts +++ b/packages/block/test/block.spec.ts @@ -193,7 +193,7 @@ tape('[Block]: block functions', function (t) { await block.validateData() st.fail('should throw') } catch (error: any) { - st.ok(error.message.includes('invalid transaction trie')) + st.ok((error.message as string).includes('invalid transaction trie')) } }) @@ -225,7 +225,7 @@ tape('[Block]: block functions', function (t) { await block.validateData() st.fail('should throw') } catch (error: any) { - st.ok(error.message.includes('invalid uncle hash')) + st.ok((error.message as string).includes('invalid uncle hash')) } }) diff --git a/packages/block/test/header.spec.ts b/packages/block/test/header.spec.ts index a972b15dbd..e4ec2c1731 100644 --- a/packages/block/test/header.spec.ts +++ b/packages/block/test/header.spec.ts @@ -187,7 +187,7 @@ tape('[Block]: Header functions', function (t) { BlockHeader.fromHeaderData({ ...data, extraData }, opts) st.fail(testCase) } catch (error: any) { - st.ok(error.message.includes('invalid amount of extra data'), testCase) + st.ok((error.message as string).includes('invalid amount of extra data'), testCase) } // PoA @@ -218,7 +218,7 @@ tape('[Block]: Header functions', function (t) { t.fail(testCase) } catch (error: any) { t.ok( - error.message.includes( + (error.message as string).includes( 'extraData must be 97 bytes on non-epoch transition blocks, received 32 bytes' ), testCase @@ -239,7 +239,7 @@ tape('[Block]: Header functions', function (t) { st.fail(testCase) } catch (error: any) { st.ok( - error.message.includes( + (error.message as string).includes( 'invalid signer list length in extraData, received signer length of 41 (not divisible by 20)' ), testCase @@ -272,7 +272,7 @@ tape('[Block]: Header functions', function (t) { await header.validate(blockchain) st.fail(testCase) } catch (error: any) { - st.ok(error.message.includes('invalid timestamp diff (lower than period)'), testCase) + st.ok((error.message as string).includes('invalid timestamp diff (lower than period)'), testCase) } testCase = 'should not throw on timestamp diff equal to period' @@ -293,7 +293,7 @@ tape('[Block]: Header functions', function (t) { await header.validate(blockchain) st.fail('should throw') } catch (error: any) { - if (error.message.includes('coinbase must be filled with zeros on epoch transition blocks')) { + if ((error.message as string).includes('coinbase must be filled with zeros on epoch transition blocks')) { st.pass('error thrown') } else { st.fail('should throw with appropriate error') @@ -309,7 +309,7 @@ tape('[Block]: Header functions', function (t) { await header.validate(blockchain) st.fail('should throw') } catch (error: any) { - if (error.message.includes('mixHash must be filled with zeros')) { + if ((error.message as string).includes('mixHash must be filled with zeros')) { st.pass('error thrown') } else { st.fail('should throw with appropriate error') @@ -324,7 +324,7 @@ tape('[Block]: Header functions', function (t) { header.validateCliqueDifficulty(blockchain) st.fail(testCase) } catch (error: any) { - if (error.message.includes('difficulty for clique block must be INTURN (2) or NOTURN (1)')) { + if ((error.message as string).includes('difficulty for clique block must be INTURN (2) or NOTURN (1)')) { st.pass('error thrown on invalid clique difficulty') } else { st.fail('should throw with appropriate error') diff --git a/packages/block/test/util.ts b/packages/block/test/util.ts index 1dc0a22152..e5ba238eb8 100644 --- a/packages/block/test/util.ts +++ b/packages/block/test/util.ts @@ -1,6 +1,6 @@ import { Chain, Common, Hardfork } from '@ethereumjs/common' import { keccak256 } from 'ethereum-cryptography/keccak' -import { bufArrToArr } from '@ethereumjs/util' +import { bufArrToArr, isTruthy } from '@ethereumjs/util' import { RLP } from 'rlp' import { Block, BlockHeader } from '../src' @@ -30,7 +30,9 @@ function createBlock( const londonHfBlock = common.hardforkBlock(Hardfork.London) const baseFeePerGas = - londonHfBlock && number > londonHfBlock ? parentBlock.header.calcNextBaseFee() : undefined + isTruthy(londonHfBlock) && number > londonHfBlock + ? parentBlock.header.calcNextBaseFee() + : undefined return Block.fromBlockData( { diff --git a/packages/blockchain/src/blockchain.ts b/packages/blockchain/src/blockchain.ts index 1cd34abed9..a1d92f5c4e 100644 --- a/packages/blockchain/src/blockchain.ts +++ b/packages/blockchain/src/blockchain.ts @@ -8,7 +8,7 @@ import { ConsensusType, Hardfork, } from '@ethereumjs/common' -import { BigIntLike } from '@ethereumjs/util' +import { BigIntLike, isFalsy, isTruthy } from '@ethereumjs/util' import { DBManager } from './db/manager' import { DBOp, DBSetBlockOrHeader, DBSetTD, DBSetHashToNumber, DBSaveLookups } from './db/helpers' @@ -335,7 +335,7 @@ export class Blockchain implements BlockchainInterface { return await this.runWithLock(async () => { // if the head is not found return the headHeader const hash = this._heads[name] ?? this._headBlockHash - if (!hash) throw new Error('No head found.') + if (isFalsy(hash)) throw new Error('No head found.') const block = await this._getBlock(hash) return block }) @@ -550,7 +550,7 @@ export class Blockchain implements BlockchainInterface { return } const parentHeader = (await this.getBlock(header.parentHash)).header - if (!parentHeader) { + if (isFalsy(parentHeader)) { throw new Error(`could not find parent header ${header.errorStr()}`) } @@ -575,7 +575,7 @@ export class Blockchain implements BlockchainInterface { header.validateGasLimit(parentHeader) - if (height) { + if (isTruthy(height)) { const dif = height - parentHeader.number if (!(dif < BigInt(8) && dif > BigInt(1))) { @@ -586,7 +586,7 @@ export class Blockchain implements BlockchainInterface { } // check blockchain dependent EIP1559 values - if (this._common.isActivatedEIP(1559)) { + if (this._common.isActivatedEIP(1559) === true) { // check if the base fee is correct let expectedBaseFee const londonHfBlock = this._common.hardforkBlock(Hardfork.London) @@ -656,7 +656,7 @@ export class Blockchain implements BlockchainInterface { let parentHash = block.header.parentHash for (let i = 0; i < getBlocks; i++) { const parentBlock = await this.getBlock(parentHash) - if (!parentBlock) { + if (isFalsy(parentBlock)) { throw new Error(`could not find parent block ${block.errorStr()}`) } canonicalBlockMap.push(parentBlock) @@ -844,7 +844,7 @@ export class Blockchain implements BlockchainInterface { // check if block is in the canonical chain const canonicalHash = await this.safeNumberToHash(blockNumber) - const inCanonical = !!canonicalHash && canonicalHash.equals(blockHash) + const inCanonical = isTruthy(canonicalHash) && canonicalHash.equals(blockHash) // delete the block, and if block is in the canonical chain, delete all // children as well @@ -889,11 +889,11 @@ export class Blockchain implements BlockchainInterface { return } - if (this._headHeaderHash?.equals(blockHash)) { + if (this._headHeaderHash?.equals(blockHash) === true) { this._headHeaderHash = headHash } - if (this._headBlockHash?.equals(blockHash)) { + if (this._headBlockHash?.equals(blockHash) === true) { this._headBlockHash = headHash } @@ -928,7 +928,7 @@ export class Blockchain implements BlockchainInterface { return await this.runWithLock(async (): Promise => { const headHash = this._heads[name] ?? this.genesisBlock.hash() - if (maxBlocks && maxBlocks < 0) { + if (isTruthy(maxBlocks) && maxBlocks < 0) { throw 'If maxBlocks is provided, it has to be a non-negative number' } @@ -1032,7 +1032,7 @@ export class Blockchain implements BlockchainInterface { let hash: Buffer | false hash = await this.safeNumberToHash(blockNumber) - while (hash) { + while (isTruthy(hash)) { ops.push(DBOp.del(DBTarget.NumberToHash, { blockNumber })) // reset stale iterator heads to current canonical head this can, for @@ -1048,7 +1048,7 @@ export class Blockchain implements BlockchainInterface { } // reset stale headBlock to current canonical - if (this._headBlockHash?.equals(hash)) { + if (this._headBlockHash?.equals(hash) === true) { this._headBlockHash = headHash } @@ -1086,7 +1086,7 @@ export class Blockchain implements BlockchainInterface { const loopCondition = async () => { staleHash = await this.safeNumberToHash(currentNumber) currentCanonicalHash = header.hash() - return !staleHash || !currentCanonicalHash.equals(staleHash) + return isFalsy(staleHash) || !currentCanonicalHash.equals(staleHash) } while (await loopCondition()) { @@ -1110,7 +1110,7 @@ export class Blockchain implements BlockchainInterface { } } // flag stale headBlock for reset - if (staleHash && this._headBlockHash?.equals(staleHash)) { + if (staleHash && this._headBlockHash?.equals(staleHash) === true) { staleHeadBlock = true } @@ -1166,7 +1166,7 @@ export class Blockchain implements BlockchainInterface { * @hidden */ private async _getHeader(hash: Buffer, number?: bigint) { - if (!number) { + if (isFalsy(number)) { number = await this.dbManager.hashToNumber(hash) } return this.dbManager.getHeader(hash, number) diff --git a/packages/blockchain/src/consensus/clique.ts b/packages/blockchain/src/consensus/clique.ts index 9d8daad624..779f8156fc 100644 --- a/packages/blockchain/src/consensus/clique.ts +++ b/packages/blockchain/src/consensus/clique.ts @@ -139,7 +139,7 @@ export class CliqueConsensus implements Consensus { const checkpointSigners = header.cliqueEpochTransitionSigners() const activeSigners = this.cliqueActiveSigners() for (const [i, cSigner] of checkpointSigners.entries()) { - if (!activeSigners[i] || !activeSigners[i].equals(cSigner)) { + if (activeSigners[i]?.equals(cSigner) !== true) { throw new Error( `checkpoint signer not found in active signers list at index ${i}: ${cSigner}` ) diff --git a/packages/blockchain/src/db/manager.ts b/packages/blockchain/src/db/manager.ts index 71ccb7bc8f..0d15759f3f 100644 --- a/packages/blockchain/src/db/manager.ts +++ b/packages/blockchain/src/db/manager.ts @@ -1,4 +1,4 @@ -import { arrToBufArr, bufferToBigInt } from '@ethereumjs/util' +import { arrToBufArr, bufferToBigInt, isFalsy, isTruthy } from '@ethereumjs/util' import { RLP } from 'rlp' import { Block, BlockHeader, BlockOptions, BlockBuffer, BlockBodyBuffer } from '@ethereumjs/block' import { Common } from '@ethereumjs/common' @@ -12,7 +12,8 @@ class NotFoundError extends Error { constructor(blockNumber: bigint) { super(`Key ${blockNumber.toString()} was not found`) - if (Error.captureStackTrace) { + // `Error.captureStackTrace` is not defined in some browser contexts + if (typeof Error.captureStackTrace !== 'undefined') { Error.captureStackTrace(this, this.constructor) } } @@ -181,8 +182,8 @@ export class DBManager { const dbKey = dbGetOperation.baseDBOp.key const dbOpts = dbGetOperation.baseDBOp - if (cacheString) { - if (!this._cache[cacheString]) { + if (isTruthy(cacheString)) { + if (isFalsy(this._cache[cacheString])) { throw new Error(`Invalid cache: ${cacheString}`) } diff --git a/packages/blockchain/src/db/operation.ts b/packages/blockchain/src/db/operation.ts index 748c2bf9e1..85576f26f6 100644 --- a/packages/blockchain/src/db/operation.ts +++ b/packages/blockchain/src/db/operation.ts @@ -1,3 +1,4 @@ +import { isTruthy } from '@ethereumjs/util' import { HEADS_KEY, HEAD_HEADER_KEY, @@ -128,7 +129,7 @@ export class DBOp { } public updateCache(cacheMap: CacheMap) { - if (this.cacheString && cacheMap[this.cacheString]) { + if (isTruthy(this.cacheString) && isTruthy(cacheMap[this.cacheString])) { if (this.baseDBOp.type == 'put') { Buffer.isBuffer(this.baseDBOp.value) && cacheMap[this.cacheString].set(this.baseDBOp.key, this.baseDBOp.value) diff --git a/packages/blockchain/src/genesisStates/index.ts b/packages/blockchain/src/genesisStates/index.ts index 112db0988b..f25f55fb95 100644 --- a/packages/blockchain/src/genesisStates/index.ts +++ b/packages/blockchain/src/genesisStates/index.ts @@ -1,6 +1,13 @@ import { SecureTrie as Trie } from '@ethereumjs/trie' import { keccak256 } from 'ethereum-cryptography/keccak' -import { Account, isHexPrefixed, toBuffer, unpadBuffer, PrefixedHexString } from '@ethereumjs/util' +import { + Account, + isHexPrefixed, + toBuffer, + unpadBuffer, + PrefixedHexString, + isTruthy, +} from '@ethereumjs/util' import { RLP } from 'rlp' export type StoragePair = [key: PrefixedHexString, value: PrefixedHexString] @@ -26,14 +33,14 @@ export async function genesisStateRoot(genesisState: GenesisState) { if (typeof value === 'string') { account.balance = BigInt(value) } else { - const [balance, code, storage] = value as AccountState - if (balance) { + const [balance, code, storage] = value as Partial + if (isTruthy(balance)) { account.balance = BigInt(balance) } - if (code) { + if (isTruthy(code)) { account.codeHash = Buffer.from(keccak256(toBuffer(code))) } - if (storage) { + if (isTruthy(storage)) { const storageTrie = new Trie() for (const [k, val] of storage) { const storageKey = isHexPrefixed(k) ? toBuffer(k) : Buffer.from(k, 'hex') diff --git a/packages/blockchain/test/blockValidation.spec.ts b/packages/blockchain/test/blockValidation.spec.ts index 86f1a9c481..8319db3397 100644 --- a/packages/blockchain/test/blockValidation.spec.ts +++ b/packages/blockchain/test/blockValidation.spec.ts @@ -86,7 +86,7 @@ tape('[Blockchain]: Block validation tests', (t) => { await blockchain.putBlock(blockWithUnclesTooOld) st.fail('cannot reach this') } catch (e: any) { - if (e.message.includes('uncle block has a parent that is too old')) + if ((e.message as string).includes('uncle block has a parent that is too old')) st.pass('block throws uncle is too old') else st.fail(`threw with wrong error ${e.message}`) } @@ -107,7 +107,7 @@ tape('[Blockchain]: Block validation tests', (t) => { await blockchain.putBlock(block1) st.fail('cannot reach this') } catch (e: any) { - if (e.message.includes('uncle block has a parent that is too old or too young')) + if ((e.message as string).includes('uncle block has a parent that is too old or too young')) st.pass('block throws uncle is too young') else st.fail(`threw with wrong error ${e.message}`) } @@ -140,7 +140,7 @@ tape('[Blockchain]: Block validation tests', (t) => { await blockchain.putBlock(block2) st.fail('cannot reach this') } catch (e: any) { - if (e.message.includes('invalid difficulty block header number=1 ')) + if ((e.message as string).includes('invalid difficulty block header number=1 ')) st.pass('block throws when uncle header is invalid') else st.fail(`threw with wrong error ${e.message}`) } @@ -162,7 +162,7 @@ tape('[Blockchain]: Block validation tests', (t) => { st.fail('cannot reach this') } catch (e: any) { - if (e.message.includes('The uncle is a canonical block')) + if ((e.message as string).includes('The uncle is a canonical block')) st.pass('block throws if an uncle is a canonical block') else st.fail(`threw with wrong error ${e.message}`) } @@ -243,7 +243,10 @@ tape('[Blockchain]: Block validation tests', (t) => { await blockchain.putBlock(block2) } catch (e: any) { const expectedError = 'Invalid block: base fee not correct' - st.ok(e.message.includes(expectedError), 'should throw when base fee is not correct') + st.ok( + (e.message as string).includes(expectedError), + 'should throw when base fee is not correct' + ) } }) diff --git a/packages/blockchain/test/clique.spec.ts b/packages/blockchain/test/clique.spec.ts index e024688a86..c8ba2b4d04 100644 --- a/packages/blockchain/test/clique.spec.ts +++ b/packages/blockchain/test/clique.spec.ts @@ -212,7 +212,9 @@ tape('Clique: Initialization', (t) => { await blockchain.putBlock(block) st.fail('should fail') } catch (error: any) { - if (error.message.includes('checkpoint signer not found in active signers list')) { + if ( + (error.message as string).includes('checkpoint signer not found in active signers list') + ) { st.pass('correct error') } else { st.fail('should fail with appropriate error') @@ -245,7 +247,11 @@ tape('Clique: Initialization', (t) => { await blockchain.putBlock(block) st.fail('should fail') } catch (error: any) { - if (error.message.includes('difficulty for clique block must be INTURN (2) or NOTURN (1)')) { + if ( + (error.message as string).includes( + 'difficulty for clique block must be INTURN (2) or NOTURN (1)' + ) + ) { st.pass('correct error') } else { st.fail('should fail with appropriate error') @@ -271,7 +277,7 @@ tape('Clique: Initialization', (t) => { await blockchain.putBlock(block) st.fail('should fail') } catch (error: any) { - if (error.message.includes('invalid clique difficulty')) { + if ((error.message as string).includes('invalid clique difficulty')) { st.pass('correct error') } else { st.fail('should fail with appropriate error') @@ -649,7 +655,7 @@ tape('Clique: Initialization', (t) => { await addNextBlock(blockchain, blocks, B) st.fail('should throw error') } catch (error: any) { - if (error.message.includes('invalid PoA block signature (clique)')) { + if ((error.message as string).includes('invalid PoA block signature (clique)')) { st.pass('correct error thrown') } else { st.fail('correct error not thrown') @@ -667,7 +673,7 @@ tape('Clique: Initialization', (t) => { await addNextBlock(blockchain, blocks, A) st.fail('should throw error') } catch (error: any) { - if (error.message.includes('recently signed')) { + if ((error.message as string).includes('recently signed')) { st.pass('correct error thrown') } else { st.fail('correct error not thrown') @@ -704,7 +710,7 @@ tape('Clique: Initialization', (t) => { await addNextBlock(blockchain, blocks, A, undefined, undefined, common) st.fail('should throw error') } catch (error: any) { - if (error.message.includes('recently signed')) { + if ((error.message as string).includes('recently signed')) { st.pass('correct error thrown') } else { st.fail('correct error not thrown') diff --git a/packages/blockchain/test/index.spec.ts b/packages/blockchain/test/index.spec.ts index 89f50a17d2..ca2ec6cdcc 100644 --- a/packages/blockchain/test/index.spec.ts +++ b/packages/blockchain/test/index.spec.ts @@ -181,7 +181,7 @@ tape('blockchain test', (t) => { await blockchain.putBlock(block) const returnedBlock = await blockchain.getBlock(1) - if (returnedBlock) { + if (typeof returnedBlock !== 'undefined') { st.ok(returnedBlock.hash().equals(blocks[1].hash())) } else { st.fail('block is not defined!') @@ -201,7 +201,7 @@ tape('blockchain test', (t) => { genesisBlock, }) const block = await blockchain.getBlock(genesisBlock.hash()) - if (block) { + if (typeof block !== 'undefined') { st.ok(block.hash().equals(genesisBlock.hash())) } else { st.fail('block is not defined!') @@ -616,7 +616,7 @@ tape('blockchain test', (t) => { const [db, genesis] = await createTestDB() const blockchain = await Blockchain.create({ db, genesisBlock: genesis }) const head = await blockchain.getIteratorHead() - if (genesis) { + if (typeof genesis !== 'undefined') { st.ok(head.hash().equals(genesis.hash()), 'should get head') st.equal( (blockchain as any)._heads['head0'].toString('hex'), @@ -665,7 +665,7 @@ tape('blockchain test', (t) => { t.test('uncached db ops', async (st) => { const [db, genesis] = await createTestDB() - if (!genesis) { + if (typeof genesis === 'undefined') { return st.fail('genesis not defined!') } const blockchain = await Blockchain.create({ db, genesisBlock: genesis }) diff --git a/packages/blockchain/test/reorg.spec.ts b/packages/blockchain/test/reorg.spec.ts index de93bca948..ffdf383ca7 100644 --- a/packages/blockchain/test/reorg.spec.ts +++ b/packages/blockchain/test/reorg.spec.ts @@ -36,7 +36,7 @@ tape('reorg tests', (t) => { while (TD_High < TD_Low) { blocks_lowTD.push(generateConsecutiveBlock(blocks_lowTD[blocks_lowTD.length - 1], 0)) blocks_highTD.push( - generateConsecutiveBlock(blocks_highTD[blocks_highTD.length - 1] || genesis, 1) + generateConsecutiveBlock(blocks_highTD[blocks_highTD.length - 1] ?? genesis, 1) ) TD_Low += blocks_lowTD[blocks_lowTD.length - 1].header.difficulty diff --git a/packages/blockchain/test/util.ts b/packages/blockchain/test/util.ts index 005be02b2e..1007306fb1 100644 --- a/packages/blockchain/test/util.ts +++ b/packages/blockchain/test/util.ts @@ -1,4 +1,4 @@ -import { bufArrToArr, toBuffer } from '@ethereumjs/util' +import { bufArrToArr, isTruthy, toBuffer } from '@ethereumjs/util' import { RLP } from 'rlp' import { Block, BlockHeader } from '@ethereumjs/block' import { Chain, Common, Hardfork } from '@ethereumjs/common' @@ -207,7 +207,9 @@ function createBlock( const londonHfBlock = common.hardforkBlock(Hardfork.London) const baseFeePerGas = - londonHfBlock && number > londonHfBlock ? parentBlock.header.calcNextBaseFee() : undefined + isTruthy(londonHfBlock) && number > londonHfBlock + ? parentBlock.header.calcNextBaseFee() + : undefined return Block.fromBlockData( { diff --git a/packages/client/bin/cli.ts b/packages/client/bin/cli.ts index 87d7051407..ed59615686 100755 --- a/packages/client/bin/cli.ts +++ b/packages/client/bin/cli.ts @@ -8,7 +8,7 @@ import { existsSync } from 'fs' import { ensureDirSync, readFileSync, removeSync } from 'fs-extra' import { Blockchain } from '@ethereumjs/blockchain' import { Chain, Common, Hardfork, ConsensusAlgorithm } from '@ethereumjs/common' -import { Address, toBuffer } from '@ethereumjs/util' +import { Address, isFalsy, isTruthy, toBuffer } from '@ethereumjs/util' import { parseMultiaddrs, parseGenesisState, @@ -19,7 +19,7 @@ import { EthereumClient } from '../lib/client' import { Config, DataDirectory, SyncMode } from '../lib/config' import { Logger, getLogger } from '../lib/logging' import { startRPCServers, helprpc } from './startRpc' -import type { FullEthereumService } from '../lib/service' +import { FullEthereumService } from '../lib/service' import { GenesisState } from '@ethereumjs/blockchain/dist/genesisStates' import { Level } from 'level' import { AbstractLevel } from 'abstract-level' @@ -328,7 +328,7 @@ async function executeBlocks(client: EthereumClient) { process.exit() } const { execution } = client.services.find((s) => s.name === 'eth') as FullEthereumService - if (!execution) throw new Error('executeBlocks requires execution') + if (isFalsy(execution)) throw new Error('executeBlocks requires execution') await execution.executeBlocks(first, last, txHashes) } @@ -337,7 +337,7 @@ async function executeBlocks(client: EthereumClient) { * Note: this is destructive and removes blocks from the blockchain. Please back up your datadir. */ async function startBlock(client: EthereumClient) { - if (!args.startBlock) return + if (isFalsy(typeof args.startBlock)) return const startBlock = BigInt(args.startBlock) const { blockchain } = client.chain const height = (await blockchain.getCanonicalHeadHeader()).number @@ -369,7 +369,7 @@ async function startClient(config: Config, customGenesisState?: GenesisState) { const dbs = initDBs(config) let blockchain - if (customGenesisState) { + if (isTruthy(customGenesisState)) { const validateConsensus = config.chainCommon.consensusAlgorithm() === ConsensusAlgorithm.Clique blockchain = await Blockchain.create({ db: dbs.chainDB, @@ -388,13 +388,13 @@ async function startClient(config: Config, customGenesisState?: GenesisState) { ...dbs, }) - if (args.startBlock) { + if (isTruthy(args.startBlock)) { await startBlock(client) } await client.open() - if (args.executeBlocks) { + if (isTruthy(args.executeBlocks)) { // Special block execution debug mode (does not change any state) await executeBlocks(client) } else { @@ -547,7 +547,7 @@ function generateAccount(): Account { * Main entry point to start a client */ async function run() { - if (args.helprpc) { + if (isTruthy(args.helprpc)) { // Output RPC help and exit return helprpc() } @@ -557,14 +557,14 @@ async function run() { // Configure accounts for mining and prefunding in a local devnet const accounts: Account[] = [] - if (args.unlock) { + if (isTruthy(args.unlock)) { accounts.push(...(await inputAccounts())) } let customGenesisState: GenesisState | undefined let common = new Common({ chain, hardfork: Hardfork.Chainstart }) - if (args.dev) { + if (isTruthy(args.dev)) { args.discDns = false if (accounts.length === 0) { // If generating new keys delete old chain data to prevent genesis block mismatch @@ -578,15 +578,17 @@ async function run() { // Configure common based on args given if ( - (args.customChainParams || args.customGenesisState || args.gethGenesis) && - (args.network !== 'mainnet' || args.networkId) + (isTruthy(args.customChainParams) || + isTruthy(args.customGenesisState) || + isTruthy(args.gethGenesis)) && + (args.network !== 'mainnet' || isTruthy(args.networkId)) ) { console.error('cannot specify both custom chain parameters and preset network ID') process.exit() } // Use custom chain parameters file if specified - if (args.customChain) { - if (!args.customGenesisState) { + if (isTruthy(args.customChain)) { + if (isFalsy(args.customGenesisState)) { console.error('cannot have custom chain parameters without genesis state') process.exit() } @@ -601,7 +603,7 @@ async function run() { console.error(`invalid chain parameters: ${err.message}`) process.exit() } - } else if (args.gethGenesis) { + } else if (isTruthy(args.gethGenesis)) { // Use geth genesis parameters file if specified const genesisFile = JSON.parse(readFileSync(args.gethGenesis, 'utf-8')) const chainName = path.parse(args.gethGenesis).base.split('.')[0] @@ -613,7 +615,7 @@ async function run() { customGenesisState = await parseGenesisState(genesisFile) } - if (args.mine && accounts.length === 0) { + if (isTruthy(args.mine) && accounts.length === 0) { console.error( 'Please provide an account to mine blocks with `--unlock [address]` or use `--dev` to generate' ) @@ -625,8 +627,8 @@ async function run() { ensureDirSync(configDirectory) const key = await Config.getClientKey(datadir, common) logger = getLogger(args) - const bootnodes = args.bootnodes ? parseMultiaddrs(args.bootnodes) : undefined - const multiaddrs = args.multiaddrs ? parseMultiaddrs(args.multiaddrs) : undefined + const bootnodes = isTruthy(args.bootnodes) ? parseMultiaddrs(args.bootnodes) : undefined + const multiaddrs = isTruthy(args.multiaddrs) ? parseMultiaddrs(args.multiaddrs) : undefined const config = new Config({ accounts, bootnodes, @@ -644,7 +646,7 @@ async function run() { maxPeers: args.maxPeers, maxPerRequest: args.maxPerRequest, maxFetcherJobs: args.maxFetcherJobs, - mine: args.mine || args.dev, + mine: isTruthy(args.mine) ? args.mine : args.dev, minerCoinbase: args.minerCoinbase, minPeers: args.minPeers, multiaddrs, @@ -658,7 +660,8 @@ async function run() { config.events.setMaxListeners(50) const client = await startClient(config, customGenesisState) - const servers = args.rpc || args.rpcEngine ? startRPCServers(client, args) : [] + const servers = + isTruthy(args.rpc) || isTruthy(args.rpcEngine) ? startRPCServers(client, args) : [] process.on('SIGINT', async () => { config.logger.info('Caught interrupt signal. Shutting down...') diff --git a/packages/client/bin/startRpc.ts b/packages/client/bin/startRpc.ts index 62483f1c25..8476aa9f7c 100644 --- a/packages/client/bin/startRpc.ts +++ b/packages/client/bin/startRpc.ts @@ -10,6 +10,7 @@ import { } from '../lib/util' import * as modules from '../lib/rpc/modules' import { Config } from '../lib/config' +import { isFalsy, isTruthy } from '@ethereumjs/util' type RPCArgs = { rpc: boolean @@ -35,11 +36,11 @@ type RPCArgs = { */ function parseJwtSecret(config: Config, jwtFilePath?: string): Buffer { let jwtSecret - if (jwtFilePath) { + if (isTruthy(jwtFilePath)) { const jwtSecretContents = readFileSync(jwtFilePath, 'utf-8').trim() const hexPattern = new RegExp(/^(0x|0X)?(?[a-fA-F0-9]+)$/, 'g') const jwtSecretHex = hexPattern.exec(jwtSecretContents)?.groups?.jwtSecret - if (!jwtSecretHex || jwtSecretHex.length != 64) { + if (isFalsy(jwtSecretHex) || jwtSecretHex.length !== 64) { throw Error('Need a valid 256 bit hex encoded secret') } config.logger.debug(`Read a hex encoded jwt secret from path=${jwtFilePath}`) @@ -103,8 +104,8 @@ export function startRPCServers(client: EthereumClient, args: RPCArgs) { jwtSecret, unlessFn: (req: any) => Array.isArray(req.body) - ? !req.body.some((r: any) => r.method.includes('engine_')) - : !req.body.method.includes('engine_'), + ? req.body.some((r: any) => r.method.includes('engine_')) === false + : req.body.method.includes('engine_') === false, } : undefined, }) diff --git a/packages/client/browser/index.ts b/packages/client/browser/index.ts index 1c9dd54819..79881a73d5 100644 --- a/packages/client/browser/index.ts +++ b/packages/client/browser/index.ts @@ -44,13 +44,14 @@ import { Config } from '../lib/config' export * from './logging' import { getLogger } from './logging' import { Level } from 'level' +import { isTruthy } from '@ethereumjs/util' export async function createClient(args: any) { const logger = getLogger({ loglevel: args.loglevel }) const datadir = args.datadir ?? Config.DATADIR_DEFAULT const common = new Common({ chain: args.network ?? Chain.Mainnet }) const key = await Config.getClientKey(datadir, common) - const bootnodes = args.bootnodes ? parseMultiaddrs(args.bootnodes) : undefined + const bootnodes = isTruthy(args.bootnodes) ? parseMultiaddrs(args.bootnodes) : undefined const config = new Config({ common, key, diff --git a/packages/client/lib/execution/receipt.ts b/packages/client/lib/execution/receipt.ts index 1e705848f5..6262d769ee 100644 --- a/packages/client/lib/execution/receipt.ts +++ b/packages/client/lib/execution/receipt.ts @@ -111,12 +111,12 @@ export class ReceiptsManager extends MetaDBManager { */ async getReceipts( blockHash: Buffer, - calcBloom?: Boolean, + calcBloom?: boolean, includeTxType?: true ): Promise async getReceipts( blockHash: Buffer, - calcBloom?: Boolean, + calcBloom?: boolean, includeTxType?: false ): Promise async getReceipts( diff --git a/packages/client/lib/execution/vmexecution.ts b/packages/client/lib/execution/vmexecution.ts index f74571a4ce..0014491485 100644 --- a/packages/client/lib/execution/vmexecution.ts +++ b/packages/client/lib/execution/vmexecution.ts @@ -6,7 +6,7 @@ import { } from '@ethereumjs/blockchain/dist/db/helpers' import { ConsensusType, Hardfork } from '@ethereumjs/common' import { VM } from '@ethereumjs/vm' -import { bufferToHex } from '@ethereumjs/util' +import { bufferToHex, isFalsy, isTruthy } from '@ethereumjs/util' import { DefaultStateManager } from '@ethereumjs/statemanager' import { LevelDB, SecureTrie as Trie } from '@ethereumjs/trie' import { short } from '../util' @@ -34,7 +34,7 @@ export class VMExecution extends Execution { constructor(options: ExecutionOptions) { super(options) - if (!this.config.vm) { + if (isFalsy(this.config.vm)) { const trie = new Trie({ db: new LevelDB(this.stateDB) }) const stateManager = new DefaultStateManager({ @@ -92,7 +92,7 @@ export class VMExecution extends Execution { const result = await this.vm.runBlock(opts) receipts = result.receipts } - if (receipts) { + if (isTruthy(receipts)) { // Save receipts this.pendingReceipts?.set(block.hash().toString('hex'), receipts) } @@ -147,7 +147,7 @@ export class VMExecution extends Execution { while ( (numExecuted === undefined || (loop && numExecuted === this.NUM_BLOCKS_PER_ITERATION)) && - !startHeadBlock.hash().equals(canonicalHead.hash()) + startHeadBlock.hash().equals(canonicalHead.hash()) === false ) { let txCounter = 0 headBlock = undefined @@ -242,23 +242,28 @@ export class VMExecution extends Execution { ) numExecuted = await this.vmPromise - if (errorBlock) { - await this.chain.blockchain.setIteratorHead('vm', (errorBlock as Block).header.parentHash) + if (isTruthy(errorBlock)) { + await this.chain.blockchain.setIteratorHead( + 'vm', + (errorBlock as unknown as Block).header.parentHash + ) return 0 } const endHeadBlock = await this.vm.blockchain.getIteratorHead('vm') - if (numExecuted && numExecuted > 0) { + if (isTruthy(numExecuted && numExecuted > 0)) { const firstNumber = startHeadBlock.header.number const firstHash = short(startHeadBlock.hash()) const lastNumber = endHeadBlock.header.number const lastHash = short(endHeadBlock.hash()) - const baseFeeAdd = this.config.execCommon.gteHardfork(Hardfork.London) - ? `baseFee=${endHeadBlock.header.baseFeePerGas} ` - : '' - const tdAdd = this.config.execCommon.gteHardfork(Hardfork.Merge) - ? '' - : `td=${this.chain.blocks.td} ` + const baseFeeAdd = + this.config.execCommon.gteHardfork(Hardfork.London) === true + ? `baseFee=${endHeadBlock.header.baseFeePerGas} ` + : '' + const tdAdd = + this.config.execCommon.gteHardfork(Hardfork.Merge) === true + ? '' + : `td=${this.chain.blocks.td} ` this.config.logger.info( `Executed blocks count=${numExecuted} first=${firstNumber} hash=${firstHash} ${tdAdd}${baseFeeAdd}hardfork=${this.hardfork} last=${lastNumber} hash=${lastHash} txs=${txCounter}` ) diff --git a/packages/client/lib/logging.ts b/packages/client/lib/logging.ts index be59b88787..1df85e69e7 100644 --- a/packages/client/lib/logging.ts +++ b/packages/client/lib/logging.ts @@ -1,3 +1,4 @@ +import { isFalsy, isTruthy } from '@ethereumjs/util' import * as chalk from 'chalk' import { createLogger, format, transports as wTransports, Logger as WinstonLogger } from 'winston' const DailyRotateFile = require('winston-daily-rotate-file') @@ -28,10 +29,10 @@ enum LevelColors { * Adds stack trace to error message if included */ const errorFormat = format((info: any) => { - if (info.message instanceof Error && info.message.stack) { + if (info.message instanceof Error && isTruthy(info.message.stack)) { return { ...info, message: info.message.stack } } - if (info instanceof Error && info.stack) { + if (info instanceof Error && isTruthy(info.stack)) { return { ...info, message: info.stack } } return info @@ -51,7 +52,7 @@ function logFormat(colors = false) { return printf((info: any) => { let level = info.level.toUpperCase() - if (!info.message) info.message = '(empty message)' + if (isFalsy(info.message)) info.message = '(empty message)' if (colors) { const colorLevel = LevelColors[info.level as keyof typeof LevelColors] @@ -61,8 +62,8 @@ function logFormat(colors = false) { const regex = /(\w+)=(.+?)(?:\s|$)/g const replaceFn = (_: any, tag: string, char: string) => `${color(tag)}=${char} ` info.message = info.message.replace(regex, replaceFn) - if (info.attentionCL) info.attentionCL = info.attentionCL.replace(regex, replaceFn) - if (info.attentionHF) info.attentionHF = info.attentionHF.replace(regex, replaceFn) + if (isTruthy(info.attentionCL)) info.attentionCL = info.attentionCL.replace(regex, replaceFn) + if (isTruthy(info.attentionHF)) info.attentionHF = info.attentionHF.replace(regex, replaceFn) } if (info.attentionCL !== undefined) attentionCL = info.attentionCL @@ -97,7 +98,7 @@ function logFileTransport(args: any) { level: args.logLevelFile, format: formatConfig(), } - if (!args.logRotate) { + if (isFalsy(args.logRotate)) { return new wTransports.File({ ...opts, filename, @@ -125,7 +126,7 @@ export function getLogger(args: { [key: string]: any } = { loglevel: 'info' }) { format: formatConfig(true), }), ] - if (args.logFile) { + if (isTruthy(args.logFile)) { transports.push(logFileTransport(args)) } const logger = createLogger({ diff --git a/packages/client/lib/miner/miner.ts b/packages/client/lib/miner/miner.ts index 29e565910e..9f15dbe0c3 100644 --- a/packages/client/lib/miner/miner.ts +++ b/packages/client/lib/miner/miner.ts @@ -2,6 +2,7 @@ import { Ethash, Solution, Miner as EthashMiner } from '@ethereumjs/ethash' import { BlockHeader } from '@ethereumjs/block' import { CliqueConsensus } from '@ethereumjs/blockchain' import { ConsensusType, Hardfork, CliqueConfig } from '@ethereumjs/common' +import { isFalsy, isTruthy } from '@ethereumjs/util' import { Event } from '../types' import { Config } from '../config' import { FullEthereumService } from '../service' @@ -75,7 +76,7 @@ export class Miner { if (!this.running) { return } - if (this.config.chainCommon.gteHardfork(Hardfork.Merge)) { + if (this.config.chainCommon.gteHardfork(Hardfork.Merge) === true) { this.config.logger.info('Miner: reached merge hardfork - stopping') this.stop() return @@ -91,7 +92,7 @@ export class Miner { const inTurn = await (blockchain.consensus as CliqueConsensus).cliqueSignerInTurn( signerAddress ) - if (!inTurn) { + if (isFalsy(inTurn)) { const signerCount = (blockchain.consensus as CliqueConsensus).cliqueActiveSigners().length timeout += Math.random() * signerCount * 500 } @@ -109,7 +110,7 @@ export class Miner { * Finds the next PoW solution. */ private async findNextSolution() { - if (!this.ethash) { + if (typeof this.ethash === 'undefined') { return } this.config.logger.info('Miner: Finding next PoW solution 🔨') @@ -190,7 +191,9 @@ export class Miner { { number }, { common: this.config.chainCommon, cliqueSigner } ) - if ((this.service.chain.blockchain as any).consensus.cliqueCheckRecentlySigned(header)) { + if ( + (this.service.chain.blockchain as any).consensus.cliqueCheckRecentlySigned(header) === true + ) { this.config.logger.info(`Miner: We have too recently signed, waiting for next block`) this.assembling = false return @@ -198,7 +201,7 @@ export class Miner { } if (this.config.chainCommon.consensusType() === ConsensusType.ProofOfWork) { - while (!this.nextSolution) { + while (isFalsy(this.nextSolution)) { this.config.logger.info(`Miner: Waiting to find next PoW solution 🔨`) await new Promise((r) => setTimeout(r, 1000)) } @@ -223,19 +226,18 @@ export class Miner { inTurn = await (vmCopy.blockchain.consensus as CliqueConsensus).cliqueSignerInTurn( signerAddress ) - difficulty = inTurn ? 2 : 1 + difficulty = isTruthy(inTurn) ? 2 : 1 } let baseFeePerGas const londonHardforkBlock = this.config.chainCommon.hardforkBlock(Hardfork.London) - const isInitialEIP1559Block = londonHardforkBlock && number === londonHardforkBlock - if (isInitialEIP1559Block) { + if (isTruthy(londonHardforkBlock) && number === londonHardforkBlock) { // Get baseFeePerGas from `paramByEIP` since 1559 not currently active on common baseFeePerGas = this.config.chainCommon.paramByEIP('gasConfig', 'initialBaseFee', 1559) ?? BigInt(0) // Set initial EIP1559 block gas limit to 2x parent gas limit per logic in `block.validateGasLimit` gasLimit = gasLimit * BigInt(2) - } else if (this.config.chainCommon.isActivatedEIP(1559)) { + } else if (this.config.chainCommon.isActivatedEIP(1559) === true) { baseFeePerGas = parentBlock.header.calcNextBaseFee() } @@ -266,7 +268,7 @@ export class Miner { const txs = await this.service.txPool.txsByPriceAndNonce(baseFeePerGas) this.config.logger.info( `Miner: Assembling block from ${txs.length} eligible txs ${ - baseFeePerGas ? `(baseFee: ${baseFeePerGas})` : '' + isTruthy(baseFeePerGas) ? `(baseFee: ${baseFeePerGas})` : '' }` ) let index = 0 @@ -300,7 +302,7 @@ export class Miner { `Miner: Sealed block with ${block.transactions.length} txs ${ this.config.chainCommon.consensusType() === ConsensusType.ProofOfWork ? `(difficulty: ${block.header.difficulty})` - : `(${inTurn ? 'in turn' : 'not in turn'})` + : `(${isTruthy(inTurn) ? 'in turn' : 'not in turn'})` }` ) this.assembling = false diff --git a/packages/client/lib/miner/pendingBlock.ts b/packages/client/lib/miner/pendingBlock.ts index 8a697098eb..c5fc82af5f 100644 --- a/packages/client/lib/miner/pendingBlock.ts +++ b/packages/client/lib/miner/pendingBlock.ts @@ -39,9 +39,8 @@ export class PendingBlock { async start(vm: VM, parentBlock: Block, headerData: Partial = {}) { const number = parentBlock.header.number + BigInt(1) const { gasLimit } = parentBlock.header - const baseFeePerGas = vm._common.isActivatedEIP(1559) - ? parentBlock.header.calcNextBaseFee() - : undefined + const baseFeePerGas = + vm._common.isActivatedEIP(1559) === true ? parentBlock.header.calcNextBaseFee() : undefined // Set the state root to ensure the resulting state // is based on the parent block's state @@ -126,7 +125,8 @@ export class PendingBlock { await this.txPool.txsByPriceAndNonce((builder as any).headerData.baseFeePerGas) ).filter( (tx) => - !(builder as any).transactions.some((t: TypedTransaction) => t.hash().equals(tx.hash())) + (builder as any).transactions.some((t: TypedTransaction) => t.hash().equals(tx.hash())) === + false ) this.config.logger.info(`Pending: Adding ${txs.length} additional eligible txs`) let index = 0 diff --git a/packages/client/lib/net/peer/rlpxpeer.ts b/packages/client/lib/net/peer/rlpxpeer.ts index 2b40d256fa..46c70fea24 100644 --- a/packages/client/lib/net/peer/rlpxpeer.ts +++ b/packages/client/lib/net/peer/rlpxpeer.ts @@ -10,6 +10,7 @@ import { Protocol, RlpxSender } from '../protocol' import { Peer, PeerOptions } from './peer' import { RlpxServer } from '../server' import { Event } from '../../types' +import { isTruthy } from '@ethereumjs/util' const devp2pCapabilities: any = { eth66: Devp2pETH.eth66, les2: Devp2pLES.les2, @@ -83,7 +84,7 @@ export class RlpxPeer extends Peer { const keys = versions.map((v: number) => name + String(v)) keys.forEach((key: any) => { const capability = devp2pCapabilities[key] - if (capability) { + if (isTruthy(capability)) { capabilities.push(capability) } }) diff --git a/packages/client/lib/net/protocol/boundprotocol.ts b/packages/client/lib/net/protocol/boundprotocol.ts index 537e4eb820..f7fc0ff8c6 100644 --- a/packages/client/lib/net/protocol/boundprotocol.ts +++ b/packages/client/lib/net/protocol/boundprotocol.ts @@ -3,6 +3,7 @@ import { Peer } from '../peer/peer' import { Sender } from './sender' import { Config } from '../../config' import { Event } from '../../types' +import { isTruthy } from '@ethereumjs/util' export interface BoundProtocolOptions { /* Config */ @@ -98,7 +99,7 @@ export class BoundProtocol { error = new Error(`Could not decode message ${message.name}: ${e}`) } const resolver = this.resolvers.get(incoming.code) - if (resolver) { + if (isTruthy(resolver)) { clearTimeout(resolver.timeout) this.resolvers.delete(incoming.code) if (error) { @@ -159,7 +160,7 @@ export class BoundProtocol { resolve: null, reject: null, } - if (this.resolvers.get(message.response!)) { + if (isTruthy(this.resolvers.get(message.response!))) { throw new Error(`Only one active request allowed per message type (${name})`) } this.resolvers.set(message.response!, resolver) diff --git a/packages/client/lib/net/protocol/flowcontrol.ts b/packages/client/lib/net/protocol/flowcontrol.ts index d548fc4a66..ebd24de5a2 100644 --- a/packages/client/lib/net/protocol/flowcontrol.ts +++ b/packages/client/lib/net/protocol/flowcontrol.ts @@ -1,4 +1,5 @@ import { Peer } from '../peer/peer' +import { isTruthy } from '@ethereumjs/util' interface Mrc { [key: string]: { @@ -66,7 +67,7 @@ export class FlowControl { const mrr = peer.les!.status.mrr const bl = peer.les!.status.bl const params = this.in.get(peer.id) ?? ({ ble: bl } as FlowParams) - if (params.last) { + if (isTruthy(params.last)) { // recharge BLE at rate of MRR when less than BL params.ble = Math.min(params.ble! + mrr * (now - params.last), bl) } @@ -88,7 +89,7 @@ export class FlowControl { handleRequest(peer: Peer, messageName: string, count: number): number { const now = Date.now() const params = this.out.get(peer.id) ?? {} - if (params.bv && params.last) { + if (isTruthy(params.bv) && isTruthy(params.last)) { params.bv = Math.min(params.bv + this.mrr * (now - params.last), this.bl) } else { params.bv = this.bl diff --git a/packages/client/lib/net/protocol/lesprotocol.ts b/packages/client/lib/net/protocol/lesprotocol.ts index 941e25887b..6a48a31760 100644 --- a/packages/client/lib/net/protocol/lesprotocol.ts +++ b/packages/client/lib/net/protocol/lesprotocol.ts @@ -1,4 +1,10 @@ -import { bigIntToBuffer, bufferToBigInt, bufferToInt, intToBuffer } from '@ethereumjs/util' +import { + bigIntToBuffer, + bufferToBigInt, + bufferToInt, + intToBuffer, + isTruthy, +} from '@ethereumjs/util' import { BlockHeader, BlockHeaderBuffer } from '@ethereumjs/block' import { Chain } from './../../blockchain' import { Message, Protocol, ProtocolOptions } from './protocol' @@ -174,7 +180,7 @@ export class LesProtocol extends Protocol { const nextFork = this.config.chainCommon.nextHardforkBlock(this.config.chainCommon.hardfork()) const forkID = [ Buffer.from(forkHash.slice(2), 'hex'), - nextFork ? bigIntToBuffer(nextFork) : Buffer.from([]), + isTruthy(nextFork) ? bigIntToBuffer(nextFork) : Buffer.from([]), ] return { @@ -194,9 +200,9 @@ export class LesProtocol extends Protocol { * @param status status message payload */ decodeStatus(status: any): any { - this.isServer = !!status.serveHeaders + this.isServer = isTruthy(status.serveHeaders) const mrc: any = {} - if (status['flowControl/MRC']) { + if (isTruthy(status['flowControl/MRC'])) { for (let entry of status['flowControl/MRC']) { entry = entry.map((e: any) => bufferToInt(e)) mrc[entry[0]] = { base: entry[1], req: entry[2] } @@ -217,9 +223,9 @@ export class LesProtocol extends Protocol { serveHeaders: this.isServer, serveChainSince: status.serveChainSince ?? 0, serveStateSince: status.serveStateSince ?? 0, - txRelay: !!status.txRelay, - bl: status['flowControl/BL'] ? bufferToInt(status['flowControl/BL']) : undefined, - mrr: status['flowControl/MRR'] ? bufferToInt(status['flowControl/MRR']) : undefined, + txRelay: isTruthy(status.txRelay), + bl: isTruthy(status['flowControl/BL']) ? bufferToInt(status['flowControl/BL']) : undefined, + mrr: isTruthy(status['flowControl/MRR']) ? bufferToInt(status['flowControl/MRR']) : undefined, mrc: mrc, } } diff --git a/packages/client/lib/net/protocol/protocol.ts b/packages/client/lib/net/protocol/protocol.ts index d992db1221..603374e1b9 100644 --- a/packages/client/lib/net/protocol/protocol.ts +++ b/packages/client/lib/net/protocol/protocol.ts @@ -1,3 +1,4 @@ +import { isTruthy } from '@ethereumjs/util' import { Config } from '../../config' import { Peer } from '../peer/peer' import { BoundProtocol } from './boundprotocol' @@ -71,12 +72,12 @@ export class Protocol { reject(new Error(`Handshake timed out after ${this.timeout}ms`)) }, this.timeout) const handleStatus = (status: any) => { - if (timeout) { + if (isTruthy(timeout)) { clearTimeout(timeout) resolve(this.decodeStatus(status)) } } - if (sender.status) { + if (isTruthy(sender.status)) { handleStatus(sender.status) } else { sender.once('status', handleStatus) diff --git a/packages/client/lib/net/server/libp2pserver.ts b/packages/client/lib/net/server/libp2pserver.ts index 556e5e8dfd..06ea52a9b5 100644 --- a/packages/client/lib/net/server/libp2pserver.ts +++ b/packages/client/lib/net/server/libp2pserver.ts @@ -6,6 +6,7 @@ import { Event, Libp2pConnection as Connection } from '../../types' import { Libp2pNode } from '../peer/libp2pnode' import { Libp2pPeer } from '../peer' import { Server, ServerOptions } from './server' +import { isTruthy } from '@ethereumjs/util' export interface Libp2pServerOptions extends ServerOptions { /* Multiaddrs to listen on */ @@ -135,7 +136,7 @@ export class Libp2pServer extends Server { */ isBanned(peerId: string): boolean { const expireTime = this.banned.get(peerId) - if (expireTime && expireTime > Date.now()) { + if (isTruthy(expireTime) && expireTime > Date.now()) { return true } this.banned.delete(peerId) diff --git a/packages/client/lib/net/server/rlpxserver.ts b/packages/client/lib/net/server/rlpxserver.ts index 1493851c0c..6b3754f89b 100644 --- a/packages/client/lib/net/server/rlpxserver.ts +++ b/packages/client/lib/net/server/rlpxserver.ts @@ -2,6 +2,7 @@ import { RLPx as Devp2pRLPx, Peer as Devp2pRLPxPeer, DPT as Devp2pDPT } from '@e import { RlpxPeer } from '../peer/rlpxpeer' import { Server, ServerOptions } from './server' import { Event } from '../../types' +import { isFalsy, isTruthy } from '@ethereumjs/util' export interface RlpxServerOptions extends ServerOptions { /* List of supported clients */ @@ -84,7 +85,7 @@ export class RlpxServer extends Server { */ getRlpxInfo() { // TODO: return undefined? note that this.rlpx might be undefined if called before initRlpx - if (!this.rlpx) { + if (isFalsy(this.rlpx)) { return { enode: undefined, id: undefined, @@ -216,7 +217,7 @@ export class RlpxServer extends Server { resolve() }) - if (this.config.port) { + if (isTruthy(this.config.port)) { this.dpt.bind(this.config.port, '0.0.0.0') } }) @@ -245,7 +246,7 @@ export class RlpxServer extends Server { protocols: Array.from(this.protocols), // @ts-ignore: Property 'server' does not exist on type 'Socket'. // TODO: check this error - inbound: !!rlpxPeer._socket.server, + inbound: isTruthy(rlpxPeer._socket?.server), }) try { await peer.accept(rlpxPeer, this) @@ -270,8 +271,8 @@ export class RlpxServer extends Server { }) this.rlpx.on('peer:error', (rlpxPeer: any, error: Error) => { - const peerId = rlpxPeer && rlpxPeer.getId() - if (!peerId) { + const peerId = isTruthy(rlpxPeer) && rlpxPeer.getId() + if (isFalsy(peerId)) { return this.error(error) } this.error(error) @@ -287,7 +288,7 @@ export class RlpxServer extends Server { resolve() }) - if (this.config.port) { + if (isTruthy(this.config.port)) { this.rlpx.listen(this.config.port, '0.0.0.0') } }) diff --git a/packages/client/lib/net/server/server.ts b/packages/client/lib/net/server/server.ts index fb48ee9f97..cc88bb9a35 100644 --- a/packages/client/lib/net/server/server.ts +++ b/packages/client/lib/net/server/server.ts @@ -1,3 +1,4 @@ +import { isTruthy } from '@ethereumjs/util' import { Multiaddr } from 'multiaddr' import { Config } from '../../config' import { MultiaddrLike, KeyLike, DnsNetwork } from '../../types' @@ -41,8 +42,8 @@ export class Server { */ constructor(options: ServerOptions) { this.config = options.config - this.key = options.key ? parseKey(options.key) : this.config.key - this.bootnodes = options.bootnodes ? parseMultiaddrs(options.bootnodes) : [] + this.key = isTruthy(options.key) ? parseKey(options.key) : this.config.key + this.bootnodes = isTruthy(options.bootnodes) ? parseMultiaddrs(options.bootnodes) : [] this.dnsNetworks = options.dnsNetworks ?? [] this.refreshInterval = options.refreshInterval ?? 30000 diff --git a/packages/client/lib/rpc/modules/engine.ts b/packages/client/lib/rpc/modules/engine.ts index a867255123..f7e31b24dd 100644 --- a/packages/client/lib/rpc/modules/engine.ts +++ b/packages/client/lib/rpc/modules/engine.ts @@ -1,6 +1,6 @@ import { Block, HeaderData } from '@ethereumjs/block' import { TransactionFactory, TypedTransaction } from '@ethereumjs/tx' -import { bufferToHex, toBuffer, zeros } from '@ethereumjs/util' +import { bufferToHex, isFalsy, isTruthy, toBuffer, zeros } from '@ethereumjs/util' import { RLP } from 'rlp' import { Trie } from '@ethereumjs/trie' import { Hardfork } from '@ethereumjs/common' @@ -270,7 +270,7 @@ export class Engine { this.service = client.services.find((s) => s.name === 'eth') as FullEthereumService this.chain = this.service.chain this.config = this.chain.config - if (!this.service.execution) { + if (isFalsy(this.service.execution)) { throw Error('execution required for engine module') } this.execution = this.service.execution @@ -372,8 +372,8 @@ export class Engine { const blockExists = await validBlock(toBuffer(blockHash), this.chain) if (blockExists) { - const isBlockExecuted = await this.vm.stateManager.hasStateRoot!(blockExists.header.stateRoot) - if (isBlockExecuted) { + const isBlockExecuted = await this.vm.stateManager.hasStateRoot(blockExists.header.stateRoot) + if (isTruthy(isBlockExecuted)) { const response = { status: Status.VALID, latestValidHash: blockHash, @@ -386,9 +386,9 @@ export class Engine { try { const parent = await this.chain.getBlock(toBuffer(parentHash)) - const isBlockExecuted = await this.vm.stateManager.hasStateRoot!(parent.header.stateRoot) + const isBlockExecuted = await this.vm.stateManager.hasStateRoot(parent.header.stateRoot) // If the parent is not executed throw an error, it will be caught and return SYNCING or ACCEPTED. - if (!isBlockExecuted) { + if (isFalsy(isBlockExecuted)) { throw new Error(`Parent block not yet executed number=${parent.header.number}`) } if (!parent._common.gteHardfork(Hardfork.Merge)) { @@ -407,9 +407,10 @@ export class Engine { if (!this.service.beaconSync && !this.config.disableBeaconSync) { await this.service.switchToBeaconSync() } - const status = (await this.service.beaconSync?.extendChain(block)) - ? Status.SYNCING - : Status.ACCEPTED + const status = + (await this.service.beaconSync?.extendChain(block)) === true + ? Status.SYNCING + : Status.ACCEPTED if (status === Status.ACCEPTED) { // Stash the block for a potential forced forkchoice update to it later. this.remoteBlocks.set(block.hash().toString('hex'), block) @@ -488,7 +489,7 @@ export class Engine { headBlock = (await this.service.beaconSync?.skeleton.getBlockByHash(toBuffer(headBlockHash))) ?? (this.remoteBlocks.get(headBlockHash.slice(2)) as Block) - if (!headBlock) { + if (isFalsy(headBlock)) { this.config.logger.debug(`Forkchoice requested unknown head hash=${short(headBlockHash)}`) const payloadStatus = { status: Status.SYNCING, @@ -540,8 +541,8 @@ export class Engine { if (this.chain.headers.latest && this.chain.headers.latest.number < headBlock.header.number) { try { const parent = await this.chain.getBlock(toBuffer(headBlock.header.parentHash)) - const isBlockExecuted = await this.vm.stateManager.hasStateRoot!(parent.header.stateRoot) - if (!isBlockExecuted) { + const isBlockExecuted = await this.vm.stateManager.hasStateRoot(parent.header.stateRoot) + if (isFalsy(isBlockExecuted)) { throw new Error(`Parent block not yet executed number=${parent.header.number}`) } parentBlocks = await recursivelyFindParents( @@ -570,7 +571,8 @@ export class Engine { const timeDiff = new Date().getTime() / 1000 - Number(headBlock.header.timestamp) if ( - (!this.config.syncTargetHeight || this.config.syncTargetHeight < headBlock.header.number) && + (isFalsy(this.config.syncTargetHeight) || + this.config.syncTargetHeight < headBlock.header.number) && timeDiff < 30 ) { this.config.synchronized = true diff --git a/packages/client/lib/rpc/modules/eth.ts b/packages/client/lib/rpc/modules/eth.ts index 4389b147af..db27f47535 100644 --- a/packages/client/lib/rpc/modules/eth.ts +++ b/packages/client/lib/rpc/modules/eth.ts @@ -32,6 +32,8 @@ import type { EthereumClient } from '../..' import type { Chain } from '../../blockchain' import type { EthProtocol } from '../../net/protocol' import type { ReceiptsManager } from '../../execution/receipt' +import { isTruthy } from '@ethereumjs/util' +import { isFalsy } from '@ethereumjs/util' type GetLogsParams = { fromBlock?: string // QUANTITY, block number or "earliest" or "latest" (default: "latest") @@ -239,10 +241,10 @@ const jsonRpcReceipt = async ( receipt.logs.map((l, i) => jsonRpcLog(l, block, tx, txIndex, logIndex + i)) ), logsBloom: bufferToHex(receipt.bitvector), - root: (receipt as PreByzantiumTxReceipt).stateRoot + root: Buffer.isBuffer((receipt as PreByzantiumTxReceipt).stateRoot) ? bufferToHex((receipt as PreByzantiumTxReceipt).stateRoot) : undefined, - status: (receipt as PostByzantiumTxReceipt).status + status: Buffer.isBuffer((receipt as PostByzantiumTxReceipt).status) ? intToHex((receipt as PostByzantiumTxReceipt).status) : undefined, }) @@ -433,7 +435,7 @@ export class Eth { const [transaction, blockOpt] = params const block = await getBlockByOption(blockOpt, this._chain) - if (!this._vm) { + if (isFalsy(this._vm)) { throw new Error('missing vm') } @@ -444,12 +446,12 @@ export class Eth { try { const runCallOpts = { - caller: from ? Address.fromString(from) : undefined, - to: to ? Address.fromString(to) : undefined, + caller: isTruthy(from) ? Address.fromString(from) : undefined, + to: isTruthy(to) ? Address.fromString(to) : undefined, gasLimit: toType(gasLimit, TypeOutput.BigInt), gasPrice: toType(gasPrice, TypeOutput.BigInt), value: toType(value, TypeOutput.BigInt), - data: data ? toBuffer(data) : undefined, + data: isTruthy(data) ? toBuffer(data) : undefined, } const { execResult } = await vm.evm.runCall(runCallOpts) return bufferToHex(execResult.returnValue) @@ -491,14 +493,14 @@ export class Eth { const [transaction, blockOpt] = params const block = await getBlockByOption(blockOpt, this._chain) - if (!this._vm) { + if (isFalsy(this._vm)) { throw new Error('missing vm') } const vm = await this._vm.copy() await vm.stateManager.setStateRoot(block.header.stateRoot) - if (!transaction.gas) { + if (isFalsy(transaction.gas)) { // If no gas limit is specified use the last block gas limit as an upper bound. const latest = await this._chain.getCanonicalHeadHeader() transaction.gas = latest.gasLimit as any @@ -508,7 +510,7 @@ export class Eth { const tx = Transaction.fromTxData(txData, { common: vm._common, freeze: false }) // set from address - const from = transaction.from ? Address.fromString(transaction.from) : Address.zero() + const from = isTruthy(transaction.from) ? Address.fromString(transaction.from) : Address.zero() tx.getSenderAddress = () => { return from } @@ -540,7 +542,7 @@ export class Eth { const address = Address.fromString(addressHex) const block = await getBlockByOption(blockOpt, this._chain) - if (!this._vm) { + if (isFalsy(this._vm)) { throw new Error('missing vm') } @@ -609,7 +611,7 @@ export class Eth { const [addressHex, blockOpt] = params const block = await getBlockByOption(blockOpt, this._chain) - if (!this._vm) { + if (isFalsy(this._vm)) { throw new Error('missing vm') } @@ -632,7 +634,7 @@ export class Eth { const [addressHex, positionHex, blockOpt] = params const block = await getBlockByOption(blockOpt, this._chain) - if (!this._vm) { + if (isFalsy(this._vm)) { throw new Error('missing vm') } @@ -643,7 +645,7 @@ export class Eth { const storageTrie = await (vm.stateManager as any)._getStorageTrie(address) const position = setLengthLeft(toBuffer(positionHex), 32) const storage = await storageTrie.get(position) - return storage + return isTruthy(storage) ? bufferToHex( setLengthLeft(Buffer.from(RLP.decode(Uint8Array.from(storage)) as Uint8Array), 32) ) @@ -684,7 +686,7 @@ export class Eth { const [addressHex, blockOpt] = params const block = await getBlockByOption(blockOpt, this._chain) - if (!this._vm) { + if (isFalsy(this._vm)) { throw new Error('missing vm') } @@ -797,7 +799,7 @@ export class Eth { } } let from: Block, to: Block - if (blockHash) { + if (isTruthy(blockHash)) { try { from = to = await this._chain.getBlock(toBuffer(blockHash)) } catch (error: any) { @@ -856,7 +858,7 @@ export class Eth { } }) let addrs - if (address) { + if (isTruthy(address)) { if (Array.isArray(address)) { addrs = address.map((a) => toBuffer(a)) } else { @@ -888,7 +890,7 @@ export class Eth { const common = this.client.config.chainCommon.copy() const { syncTargetHeight } = this.client.config - if (!syncTargetHeight && !this.client.config.mine) { + if (isFalsy(syncTargetHeight) && !this.client.config.mine) { throw { code: INTERNAL_ERROR, message: `client is not aware of the current chain height yet (give sync some more time)`, @@ -896,7 +898,7 @@ export class Eth { } // Set the tx common to an appropriate HF to create a tx // with matching HF rules - if (syncTargetHeight) { + if (isTruthy(syncTargetHeight)) { common.setHardforkByBlockNumber(syncTargetHeight) } @@ -957,7 +959,7 @@ export class Eth { const [addressHex, slotsHex, blockOpt] = params const block = await getBlockByOption(blockOpt, this._chain) - if (!this._vm) { + if (isFalsy(this._vm)) { throw new Error('missing vm') } @@ -996,7 +998,7 @@ export class Eth { const startingBlock = bigIntToHex(synchronizer.startingBlock) let highestBlock - if (syncTargetHeight) { + if (isTruthy(syncTargetHeight)) { highestBlock = bigIntToHex(syncTargetHeight) } else { const bestPeer = await synchronizer.best() diff --git a/packages/client/lib/rpc/util/CLConnectionManager.ts b/packages/client/lib/rpc/util/CLConnectionManager.ts index c31a8f07d6..1acfe584d8 100644 --- a/packages/client/lib/rpc/util/CLConnectionManager.ts +++ b/packages/client/lib/rpc/util/CLConnectionManager.ts @@ -9,6 +9,7 @@ import { ForkchoiceStateV1, PayloadStatusV1, } from '../modules/engine' +import { isTruthy } from '@ethereumjs/util' export enum ConnectionStatus { Connected = 'connected', @@ -79,11 +80,11 @@ export class CLConnectionManager { maximumFractionDigits: 1, }) - if (this.config.chainCommon.gteHardfork(Hardfork.MergeForkIdTransition)) { + if (this.config.chainCommon.gteHardfork(Hardfork.MergeForkIdTransition) === true) { this.start() } else { this.config.events.on(Event.CHAIN_UPDATED, () => { - if (this.config.chainCommon.gteHardfork(Hardfork.MergeForkIdTransition)) { + if (this.config.chainCommon.gteHardfork(Hardfork.MergeForkIdTransition) === true) { this.start() } }) @@ -149,7 +150,7 @@ export class CLConnectionManager { if (update.headBlock) { msg += ` timestampDiff=${this.timeDiffStr(update.headBlock)}` } - if (update.error) { + if (isTruthy(update.error)) { msg += ` error=${update.error}` } return msg diff --git a/packages/client/lib/rpc/validation.ts b/packages/client/lib/rpc/validation.ts index df0e192414..4eb64a7737 100644 --- a/packages/client/lib/rpc/validation.ts +++ b/packages/client/lib/rpc/validation.ts @@ -1,4 +1,5 @@ import { INVALID_PARAMS } from './error-code' +import { isFalsy, isTruthy } from '@ethereumjs/util' /** * middleware for parameters validation @@ -19,10 +20,10 @@ export function middleware(method: any, requiredParamsCount: number, validators: } for (let i = 0; i < validators.length; i++) { - if (validators[i]) { + if (isTruthy(validators[i])) { for (let j = 0; j < validators[i].length; j++) { const error = validators[i][j](params, i) - if (error) { + if (isTruthy(error)) { return reject(error) } } @@ -196,7 +197,7 @@ export const validators = { const tx = params[index] for (const field of requiredFields) { - if (!tx[field]) { + if (isFalsy(tx[field])) { return { code: INVALID_PARAMS, message: `invalid argument ${index}: required field ${field}`, @@ -205,21 +206,21 @@ export const validators = { } const validate = (field: any, validator: Function) => { - if (!field) return + if (isFalsy(field)) return const v = validator([field], 0) - if (v) return v + if (isTruthy(v)) return v } // validate addresses for (const field of [tx.to, tx.from]) { const v = validate(field, this.address) - if (v) return v + if (isTruthy(v)) return v } - // valdiate hex + // validate hex for (const field of [tx.gas, tx.gasPrice, tx.value, tx.data]) { const v = validate(field, this.hex) - if (v) return v + if (isTruthy(v)) return v } } } @@ -245,7 +246,7 @@ export const validators = { for (const [key, validator] of Object.entries(form)) { const value = params[index][key] const result = validator([value], 0) - if (result) { + if (isTruthy(result)) { // add key to message for context const originalMessage = result.message.split(':') const message = `invalid argument ${index} for key '${key}':${originalMessage[1]}` @@ -275,7 +276,7 @@ export const validators = { } for (const value of params[index]) { const result = validator([value], 0) - if (result) return result + if (isTruthy(result)) return result } } } @@ -312,7 +313,7 @@ export const validators = { get optional() { return (validator: any) => { return (params: any, index: number) => { - if (!params[index]) { + if (isFalsy(params[index])) { return } return validator(params, index) @@ -330,7 +331,7 @@ export const validators = { get either() { return (...validators: any) => { return (params: any, index: number) => { - if (!params[index]) { + if (isFalsy(params[index])) { return } const results = validators.map((v: any) => v(params, index)) diff --git a/packages/client/lib/service/fullethereumservice.ts b/packages/client/lib/service/fullethereumservice.ts index baed08efaa..ded061ac14 100644 --- a/packages/client/lib/service/fullethereumservice.ts +++ b/packages/client/lib/service/fullethereumservice.ts @@ -12,6 +12,7 @@ import { Miner } from '../miner' import { VMExecution } from '../execution' import type { Block } from '@ethereumjs/block' +import { isFalsy, isTruthy } from '@ethereumjs/util' interface FullEthereumServiceOptions extends EthereumServiceOptions { /** Serve LES requests (default: false) */ @@ -51,7 +52,7 @@ export class FullEthereumService extends EthereumService { service: this, }) - if (this.config.chainCommon.gteHardfork(Hardfork.Merge)) { + if (this.config.chainCommon.gteHardfork(Hardfork.Merge) === true) { if (!this.config.disableBeaconSync) { void this.switchToBeaconSync() } @@ -209,8 +210,8 @@ export class FullEthereumService extends EthereumService { const { reqId, block, max, skip, reverse } = message.data if (typeof block === 'bigint') { if ( - (reverse && block > this.chain.headers.height) || - (!reverse && block + BigInt(max * skip) > this.chain.headers.height) + (isTruthy(reverse) && block > this.chain.headers.height) || + (isFalsy(reverse) && block + BigInt(max * skip) > this.chain.headers.height) ) { // Don't respond to requests greater than the current height return @@ -226,7 +227,7 @@ export class FullEthereumService extends EthereumService { const bodies = blocks.map((block) => block.raw().slice(1)) peer.eth!.send('BlockBodies', { reqId, bodies }) } else if (message.name === 'NewBlockHashes') { - if (this.config.chainCommon.gteHardfork(Hardfork.Merge)) { + if (this.config.chainCommon.gteHardfork(Hardfork.Merge) === true) { this.config.logger.debug( `Dropping peer ${peer.id} for sending NewBlockHashes after merge (EIP-3675)` ) @@ -237,7 +238,7 @@ export class FullEthereumService extends EthereumService { } else if (message.name === 'Transactions') { await this.txPool.handleAnnouncedTxs(message.data, peer, this.pool) } else if (message.name === 'NewBlock') { - if (this.config.chainCommon.gteHardfork(Hardfork.Merge)) { + if (this.config.chainCommon.gteHardfork(Hardfork.Merge) === true) { this.config.logger.debug( `Dropping peer ${peer.id} for sending NewBlock after merge (EIP-3675)` ) @@ -260,7 +261,7 @@ export class FullEthereumService extends EthereumService { let receiptsSize = 0 for (const hash of hashes) { const blockReceipts = await receiptsManager.getReceipts(hash, true, true) - if (!blockReceipts) continue + if (isFalsy(blockReceipts)) continue receipts.push(...blockReceipts) const receiptsBuffer = Buffer.concat(receipts.map((r) => encodeReceipt(r, r.txType))) receiptsSize += Buffer.byteLength(receiptsBuffer) @@ -288,8 +289,8 @@ export class FullEthereumService extends EthereumService { } else { if (typeof block === 'bigint') { if ( - (reverse && block > this.chain.headers.height) || - (!reverse && block + BigInt(max * skip) > this.chain.headers.height) + (isTruthy(reverse) && block > this.chain.headers.height) || + (isFalsy(reverse) && block + BigInt(max * skip) > this.chain.headers.height) ) { // Don't respond to requests greater than the current height return diff --git a/packages/client/lib/service/txpool.ts b/packages/client/lib/service/txpool.ts index 4ca194bf3b..be6cfe1c3d 100644 --- a/packages/client/lib/service/txpool.ts +++ b/packages/client/lib/service/txpool.ts @@ -5,7 +5,7 @@ import { Transaction, TypedTransaction, } from '@ethereumjs/tx' -import { Address, bufferToHex } from '@ethereumjs/util' +import { Address, bufferToHex, isFalsy, isTruthy } from '@ethereumjs/util' import { Config } from '../config' import { Peer } from '../net/peer' import type { VM } from '@ethereumjs/vm' @@ -193,7 +193,7 @@ export class TxPool { * Checks if tx pool should be started */ checkRunState() { - if (this.running || !this.config.syncTargetHeight) return + if (this.running || isFalsy(this.config.syncTargetHeight)) return // If height gte target, we are close enough to the // head of the chain that the tx pool can be started const target = @@ -264,7 +264,7 @@ export class TxPool { } } const block = await this.service.chain.getCanonicalHeadHeader() - if (block.baseFeePerGas) { + if (isTruthy(block.baseFeePerGas)) { if (currentGasPrice.maxFee < block.baseFeePerGas / BigInt(2) && !isLocalTransaction) { throw new Error( `Tx cannot pay basefee of ${block.baseFeePerGas}, have ${currentGasPrice.maxFee} (not within 50% range of current basefee)` @@ -502,7 +502,9 @@ export class TxPool { // Remove from pending list regardless if tx is in result this.pending = this.pending.filter((hash) => !reqHashesStr.includes(hash)) - if (!getPooledTxs) return + if (isFalsy(getPooledTxs)) { + return + } const [_, txs] = getPooledTxs this.config.logger.debug(`TxPool: received requested txs number=${txs.length}`) @@ -573,7 +575,7 @@ export class TxPool { */ private normalizedGasPrice(tx: TypedTransaction, baseFee?: bigint) { const supports1559 = tx.supports(Capability.EIP1559FeeMarket) - if (baseFee) { + if (isTruthy(baseFee)) { if (supports1559) { return (tx as FeeMarketEIP1559Transaction).maxPriorityFeePerGas } else { @@ -645,7 +647,7 @@ export class TxPool { // therefore no txs from this address are currently executable continue } - if (baseFee) { + if (isTruthy(baseFee)) { // If any tx has an insufficient gasPrice, // remove all txs after that since they cannot be executed const found = txsSortedByNonce.findIndex((tx) => this.normalizedGasPrice(tx) < baseFee) diff --git a/packages/client/lib/sync/beaconsync.ts b/packages/client/lib/sync/beaconsync.ts index 876417fe06..08b600531e 100644 --- a/packages/client/lib/sync/beaconsync.ts +++ b/packages/client/lib/sync/beaconsync.ts @@ -6,6 +6,7 @@ import type { Block } from '@ethereumjs/block' import type { Peer } from '../net/peer/peer' import { errSyncReorged, Skeleton } from './skeleton' import type { VMExecution } from '../execution' +import { isFalsy, isTruthy } from '@ethereumjs/util' interface BeaconSynchronizerOptions extends SynchronizerOptions { /** Skeleton chain */ @@ -55,7 +56,7 @@ export class BeaconSynchronizer extends Synchronizer { this.config.events.on(Event.CHAIN_UPDATED, this.runExecution) const subchain = this.skeleton.bounds() - if (subchain) { + if (isTruthy(subchain)) { const { head, tail, next } = subchain this.config.logger.info(`Resuming beacon sync head=${head} tail=${tail} next=${short(next)}`) } @@ -196,7 +197,7 @@ export class BeaconSynchronizer extends Synchronizer { if (!latest) return false const height = latest.number - if (!this.config.syncTargetHeight || this.config.syncTargetHeight < latest.number) { + if (isFalsy(this.config.syncTargetHeight) || this.config.syncTargetHeight < latest.number) { this.config.syncTargetHeight = height this.config.logger.info(`New sync target height=${height} hash=${short(latest.hash())}`) } @@ -204,11 +205,9 @@ export class BeaconSynchronizer extends Synchronizer { const { tail } = this.skeleton.bounds() const first = tail - BigInt(1) // Sync from tail to next subchain or chain height + const subChainHead = (this.skeleton as any).status.progress.subchains[1]?.head const count = - first - - ((this.skeleton as any).status.progress.subchains[1]?.head - ? (this.skeleton as any).status.progress.subchains[1].head - BigInt(1) - : this.chain.blocks.height) + first - (isTruthy(subChainHead) ? subChainHead - BigInt(1) : this.chain.blocks.height) if (count > BigInt(0) && (!this.fetcher || this.fetcher.errored)) { this.fetcher = new ReverseBlockFetcher({ config: this.config, @@ -249,7 +248,7 @@ export class BeaconSynchronizer extends Synchronizer { // Execute single block when within 50 blocks of head, // otherwise run execution in batch of 50 blocks when filling canonical chain. if ( - (this.skeleton.bounds() && + (isTruthy(this.skeleton.bounds()) && this.chain.blocks.height > this.skeleton.bounds().head - BigInt(50)) || this.chain.blocks.height % BigInt(50) === BigInt(0) ) { diff --git a/packages/client/lib/sync/fetcher/blockfetcher.ts b/packages/client/lib/sync/fetcher/blockfetcher.ts index 230aa2b698..c9a0883189 100644 --- a/packages/client/lib/sync/fetcher/blockfetcher.ts +++ b/packages/client/lib/sync/fetcher/blockfetcher.ts @@ -1,5 +1,5 @@ import { Block, BlockBuffer } from '@ethereumjs/block' -import { KECCAK256_RLP, KECCAK256_RLP_ARRAY } from '@ethereumjs/util' +import { isFalsy, KECCAK256_RLP, KECCAK256_RLP_ARRAY } from '@ethereumjs/util' import { Peer } from '../../net/peer' import { Job } from './types' import { BlockFetcherBase, JobTask, BlockFetcherOptions } from './blockfetcherbase' @@ -40,14 +40,14 @@ export class BlockFetcher extends BlockFetcherBase { max: count, reverse: this.reverse, }) - if (!headersResult || headersResult[1].length === 0) { + if (isFalsy(headersResult) || headersResult[1].length === 0) { // Catch occasional null or empty responses this.debug(`Peer ${peerInfo} returned no headers for blocks=${blocksRange}`) return [] } const headers = headersResult[1] const bodiesResult = await peer!.eth!.getBlockBodies({ hashes: headers.map((h) => h.hash()) }) - if (!bodiesResult || bodiesResult[1].length === 0) { + if (isFalsy(bodiesResult) || bodiesResult[1].length === 0) { // Catch occasional null or empty responses this.debug(`Peer ${peerInfo} returned no bodies for blocks=${blocksRange}`) return [] diff --git a/packages/client/lib/sync/fetcher/fetcher.ts b/packages/client/lib/sync/fetcher/fetcher.ts index 9b4d0e02a6..d97352a5c3 100644 --- a/packages/client/lib/sync/fetcher/fetcher.ts +++ b/packages/client/lib/sync/fetcher/fetcher.ts @@ -7,6 +7,7 @@ import { Config } from '../../config' import { Event } from '../../types' import { Job } from './types' import { JobTask as BlockFetcherJobTask } from './blockfetcherbase' +import { isTruthy } from '@ethereumjs/util' export interface FetcherOptions { /* Common chain config*/ @@ -146,7 +147,7 @@ export abstract class Fetcher extends Readable if (this.running) { // If the job was already dequeued, for example coming from writer pipe, processed // needs to be decreased - if (dequeued) this.processed-- + if (dequeued === true) this.processed-- this.in.insert({ ...job, @@ -261,7 +262,7 @@ export abstract class Fetcher extends Readable dequeued?: boolean ) { const jobItems = job instanceof Array ? job : [job] - if (irrecoverable) { + if (irrecoverable === true) { this.pool.ban(jobItems[0].peer!, this.banTime) } else { void this.wait().then(() => { @@ -368,7 +369,7 @@ export abstract class Fetcher extends Readable if (this.running) { this.config.events.emit(Event.SYNC_FETCHER_ERROR, error, job?.task, job?.peer) } - if (irrecoverable) { + if (irrecoverable === true) { this.running = false this.errored = error this.clear() @@ -395,7 +396,7 @@ export abstract class Fetcher extends Readable } catch (error: any) { this.config.logger.warn(`Error storing received block or header result: ${error}`) if ( - error.message.includes('could not find parent header') && + (error.message as string).includes('could not find parent header') && this.isBlockFetcherJobTask(jobItems[0].task) ) { // Non-fatal error: ban peer and re-enqueue job. @@ -460,7 +461,7 @@ export abstract class Fetcher extends Readable this.nextTasks() while (this.running) { - if (!this.next()) { + if (this.next() === false) { if (this.finished === this.total && this.destroyWhenDone) { this.push(null) } @@ -532,6 +533,6 @@ export abstract class Fetcher extends Readable * @param task */ private isBlockFetcherJobTask(task: JobTask | BlockFetcherJobTask): task is BlockFetcherJobTask { - return task && 'first' in task && 'count' in task + return isTruthy(task) && 'first' in task && 'count' in task } } diff --git a/packages/client/lib/sync/fullsync.ts b/packages/client/lib/sync/fullsync.ts index 64f589a532..4d539a616a 100644 --- a/packages/client/lib/sync/fullsync.ts +++ b/packages/client/lib/sync/fullsync.ts @@ -7,6 +7,7 @@ import { BlockFetcher } from './fetcher' import { VMExecution } from '../execution' import type { Block } from '@ethereumjs/block' import type { TxPool } from '../service/txpool' +import { isFalsy, isTruthy } from '@ethereumjs/util' interface FullSynchronizerOptions extends SynchronizerOptions { /** Tx Pool */ @@ -87,7 +88,7 @@ export class FullSynchronizer extends Synchronizer { const peers = this.pool.peers.filter(this.syncable.bind(this)) if (peers.length < this.config.minPeers && !this.forceSync) return for (const peer of peers) { - if (peer.eth?.status) { + if (typeof peer.eth !== 'undefined' && isTruthy(peer.eth.status)) { const td = peer.eth.status.td if ( (!best && td >= this.chain.blocks.td) || @@ -115,7 +116,7 @@ export class FullSynchronizer extends Synchronizer { * Checks if tx pool should be started */ checkTxPoolState() { - if (!this.config.syncTargetHeight || this.txPool.running) { + if (isFalsy(this.config.syncTargetHeight) || this.txPool.running) { return } // If height gte target, we are close enough to the @@ -137,7 +138,7 @@ export class FullSynchronizer extends Synchronizer { if (!latest) return false const height = latest.number - if (!this.config.syncTargetHeight || this.config.syncTargetHeight < latest.number) { + if (isFalsy(this.config.syncTargetHeight) || this.config.syncTargetHeight < latest.number) { this.config.syncTargetHeight = height this.config.logger.info(`New sync target height=${height} hash=${short(latest.hash())}`) } @@ -174,7 +175,7 @@ export class FullSynchronizer extends Synchronizer { * Process blocks fetched from the fetcher. */ async processBlocks(blocks: Block[]) { - if (this.config.chainCommon.gteHardfork(Hardfork.Merge)) { + if (this.config.chainCommon.gteHardfork(Hardfork.Merge) === true) { if (this.fetcher !== null) { // If we are beyond the merge block we should stop the fetcher this.config.logger.info('Merge hardfork reached, stopping block fetcher') @@ -192,9 +193,10 @@ export class FullSynchronizer extends Synchronizer { const first = BigInt(blocks[0].header.number) const last = BigInt(blocks[blocks.length - 1].header.number) const hash = short(blocks[0].hash()) - const baseFeeAdd = this.config.chainCommon.gteHardfork(Hardfork.London) - ? `baseFee=${blocks[0].header.baseFeePerGas} ` - : '' + const baseFeeAdd = + this.config.chainCommon.gteHardfork(Hardfork.London) === true + ? `baseFee=${blocks[0].header.baseFeePerGas} ` + : '' let attentionHF: string | null = null const nextHFBlockNum = this.config.chainCommon.nextHardforkBlock() @@ -207,7 +209,7 @@ export class FullSynchronizer extends Synchronizer { } else { if ( this.config.chainCommon.hardfork() === Hardfork.MergeForkIdTransition && - !this.config.chainCommon.gteHardfork(Hardfork.Merge) + this.config.chainCommon.gteHardfork(Hardfork.Merge) === false ) { const mergeTD = this.config.chainCommon.hardforkTD(Hardfork.Merge)! const td = this.chain.blocks.td @@ -294,12 +296,12 @@ export class FullSynchronizer extends Synchronizer { // https://github.com/ethereum/devp2p/blob/master/caps/eth.md#block-propagation const numPeersToShareWith = Math.floor(Math.sqrt(this.pool.peers.length)) await this.sendNewBlock(block, this.pool.peers.slice(0, numPeersToShareWith)) - if (this.chain.blocks.latest?.hash().equals(block.header.parentHash)) { + if (this.chain.blocks.latest?.hash().equals(block.header.parentHash) === true) { // If new block is child of current chain tip, insert new block into chain await this.chain.putBlocks([block]) // Check if new sync target height can be set const blockNumber = block.header.number - if (!this.config.syncTargetHeight || blockNumber > this.config.syncTargetHeight) { + if (isFalsy(this.config.syncTargetHeight) || blockNumber > this.config.syncTargetHeight) { this.config.syncTargetHeight = blockNumber } } else { @@ -332,7 +334,8 @@ export class FullSynchronizer extends Synchronizer { } // Check if new sync target height can be set if (newSyncHeight && blockNumber <= newSyncHeight[1]) continue - if (this.config.syncTargetHeight && blockNumber <= this.config.syncTargetHeight) continue + if (isTruthy(this.config.syncTargetHeight) && blockNumber <= this.config.syncTargetHeight) + continue newSyncHeight = value } diff --git a/packages/client/lib/sync/lightsync.ts b/packages/client/lib/sync/lightsync.ts index 01654cd928..147792f287 100644 --- a/packages/client/lib/sync/lightsync.ts +++ b/packages/client/lib/sync/lightsync.ts @@ -5,6 +5,7 @@ import { Synchronizer, SynchronizerOptions } from './sync' import { HeaderFetcher } from './fetcher' import { Event } from '../types' import type { BlockHeader } from '@ethereumjs/block' +import { isFalsy } from '@ethereumjs/util' /** * Implements an ethereum light sync synchronizer @@ -89,7 +90,7 @@ export class LightSynchronizer extends Synchronizer { if (!latest) return false const height = peer!.les!.status.headNum - if (!this.config.syncTargetHeight || this.config.syncTargetHeight < height) { + if (isFalsy(this.config.syncTargetHeight) || this.config.syncTargetHeight < height) { this.config.syncTargetHeight = height this.config.logger.info(`New sync target height=${height} hash=${short(latest.hash())}`) } @@ -133,9 +134,10 @@ export class LightSynchronizer extends Synchronizer { } const first = headers[0].number const hash = short(headers[0].hash()) - const baseFeeAdd = this.config.chainCommon.gteHardfork(Hardfork.London) - ? `baseFee=${headers[0].baseFeePerGas} ` - : '' + const baseFeeAdd = + this.config.chainCommon.gteHardfork(Hardfork.London) === true + ? `baseFee=${headers[0].baseFeePerGas} ` + : '' this.config.logger.info( `Imported headers count=${headers.length} number=${first} hash=${hash} ${baseFeeAdd}peers=${this.pool.size}` ) diff --git a/packages/client/lib/sync/skeleton.ts b/packages/client/lib/sync/skeleton.ts index 4210787e92..e6822bf671 100644 --- a/packages/client/lib/sync/skeleton.ts +++ b/packages/client/lib/sync/skeleton.ts @@ -165,7 +165,7 @@ export class Skeleton extends MetaDBManager { const lastchain = this.status.progress.subchains[0] if (lastchain.head === headchain.tail - BigInt(1)) { const lasthead = await this.getBlock(lastchain.head) - if (lasthead?.hash().equals(head.header.parentHash)) { + if (lasthead?.hash().equals(head.header.parentHash) === true) { this.config.logger.debug( `Extended skeleton subchain with new head=${headchain.tail} tail=${lastchain.tail}` ) @@ -208,7 +208,7 @@ export class Skeleton extends MetaDBManager { // once more, ignore it instead of tearing down sync for a noop. if (lastchain.head === lastchain.tail) { const block = await this.getBlock(number) - if (block?.hash().equals(head.hash())) { + if (block?.hash().equals(head.hash()) === true) { return false } } @@ -326,7 +326,7 @@ export class Skeleton extends MetaDBManager { if ( (await this.getBlock(this.status.progress.subchains[1].head)) ?.hash() - .equals(this.status.progress.subchains[0].next) + .equals(this.status.progress.subchains[0].next) === true ) { this.config.logger.debug( `Previous subchain merged head=${head} tail=${tail} next=${short(next)}` diff --git a/packages/client/lib/sync/sync.ts b/packages/client/lib/sync/sync.ts index fb81f47159..b35a4c0d3b 100644 --- a/packages/client/lib/sync/sync.ts +++ b/packages/client/lib/sync/sync.ts @@ -7,6 +7,7 @@ import { Chain } from '../blockchain' import { Event } from '../types' import { BlockFetcher, HeaderFetcher, ReverseBlockFetcher } from './fetcher' import { short } from '../util' +import { isFalsy, isTruthy } from '@ethereumjs/util' export interface SynchronizerOptions { /* Config */ @@ -100,7 +101,7 @@ export abstract class Synchronizer { * Start synchronization */ async start(): Promise { - if (this.running || this.config.chainCommon.gteHardfork(Hardfork.Merge)) { + if (this.running || this.config.chainCommon.gteHardfork(Hardfork.Merge) === true) { return false } this.running = true @@ -113,7 +114,7 @@ export abstract class Synchronizer { const timeout = setTimeout(() => { this.forceSync = true }, this.interval * 30) - while (this.running && !this.config.chainCommon.gteHardfork(Hardfork.Merge)) { + while (this.running && this.config.chainCommon.gteHardfork(Hardfork.Merge) === false) { try { await this.sync() } catch (error: any) { @@ -134,7 +135,7 @@ export abstract class Synchronizer { * @emits {@link Event.SYNC_SYNCHRONIZED} */ updateSynchronizedState() { - if (!this.config.syncTargetHeight) { + if (isFalsy(this.config.syncTargetHeight)) { return } if (this.chain.headers.height >= this.config.syncTargetHeight) { @@ -172,7 +173,7 @@ export abstract class Synchronizer { const resolveSync = (height?: number) => { this.clearFetcher() resolve(true) - const heightStr = height ? ` height=${height}` : '' + const heightStr = isTruthy(height) ? ` height=${height}` : '' this.config.logger.debug( `Finishing up sync with the current fetcher${heightStr} }` @@ -231,7 +232,7 @@ export abstract class Synchronizer { * Reset synced status after a certain time with no chain updates */ _syncedStatusCheck() { - if (this.config.chainCommon.gteHardfork(Hardfork.Merge)) { + if (this.config.chainCommon.gteHardfork(Hardfork.Merge) === true) { return } diff --git a/packages/client/lib/util/index.ts b/packages/client/lib/util/index.ts index 630c14cad6..03304134a4 100644 --- a/packages/client/lib/util/index.ts +++ b/packages/client/lib/util/index.ts @@ -1,6 +1,7 @@ /** * @module util */ +import { isFalsy } from '@ethereumjs/util' import { platform } from 'os' import { version as packageVersion } from '../../package.json' @@ -8,7 +9,7 @@ export * from './parse' export * from './rpc' export function short(buf: Buffer | string): string { - if (!buf) return '' + if (isFalsy(buf)) return '' const bufStr = Buffer.isBuffer(buf) ? `0x${buf.toString('hex')}` : buf let str = bufStr.substring(0, 6) + '…' if (bufStr.length === 66) { diff --git a/packages/client/lib/util/parse.ts b/packages/client/lib/util/parse.ts index be6bb9f24f..7d4ef97dae 100644 --- a/packages/client/lib/util/parse.ts +++ b/packages/client/lib/util/parse.ts @@ -5,7 +5,9 @@ import { addHexPrefix, bigIntToHex, intToHex, + isFalsy, isHexPrefixed, + isTruthy, stripHexPrefix, } from '@ethereumjs/util' import type { MultiaddrLike } from '../types' @@ -17,7 +19,7 @@ import type { Common } from '@ethereumjs/common' * @param input comma separated string */ export function parseMultiaddrs(input: MultiaddrLike): Multiaddr[] { - if (!input) { + if (isFalsy(input)) { return [] } if (!Array.isArray(input) && typeof input === 'object') { @@ -43,7 +45,7 @@ export function parseMultiaddrs(input: MultiaddrLike): Multiaddr[] { // parse as object if (typeof s === 'object') { const { ip, port } = s as any - if (ip && port) { + if (isTruthy(ip) && isTruthy(port)) { return multiaddr(`/ip4/${ip}/tcp/${port}`) } } @@ -143,7 +145,7 @@ async function parseGethParams(json: any) { baseFeePerGas, }, bootstrapNodes: [], - consensus: config.clique + consensus: isTruthy(config.clique) ? { type: 'poa', algorithm: 'clique', @@ -200,7 +202,7 @@ export async function parseCustomParams(json: any, name?: string) { if (['config', 'difficulty', 'gasLimit', 'alloc'].some((field) => !(field in json))) { throw new Error('Invalid format, expected geth genesis fields missing') } - if (name) { + if (isTruthy(name)) { json.name = name } return parseGethParams(json) @@ -219,8 +221,8 @@ export async function parseGenesisState(json: any) { let { balance, code, storage } = json.alloc[address] address = addHexPrefix(address) balance = isHexPrefixed(balance) ? balance : bigIntToHex(BigInt(balance)) - code = code ? addHexPrefix(code) : undefined - storage = storage ? Object.entries(storage) : undefined + code = isTruthy(code) ? addHexPrefix(code) : undefined + storage = isTruthy(storage) ? Object.entries(storage) : undefined state[address] = [balance, code, storage] as any } return state @@ -244,7 +246,11 @@ export function parseKey(input: string | Buffer) { */ export function setCommonForkHashes(common: Common, genesisHash: Buffer) { for (const hf of (common as any)._chainParams.hardforks) { - if (!hf.forkHash && hf.block !== undefined && (hf.block !== null || hf.td !== undefined)) { + if ( + isFalsy(hf.forkHash) && + typeof hf.block !== 'undefined' && + (hf.block !== null || typeof hf.td !== 'undefined') + ) { hf.forkHash = common.forkHash(hf.name, genesisHash) } } diff --git a/packages/client/lib/util/rpc.ts b/packages/client/lib/util/rpc.ts index 41252547ff..9b660a8900 100644 --- a/packages/client/lib/util/rpc.ts +++ b/packages/client/lib/util/rpc.ts @@ -7,6 +7,7 @@ import * as cors from 'cors' import { inspect } from 'util' import { RPCManager } from '../rpc' import { Logger } from '../logging' +import { isTruthy } from '@ethereumjs/util' type IncomingMessage = Connect.IncomingMessage const algorithm: TAlgorithm = 'HS256' @@ -43,7 +44,7 @@ export function inspectParams(params: any, shorten?: number) { colors: true, maxStringLength: 100, } as any) - if (shorten) { + if (isTruthy(shorten)) { inspected = inspected.replace(/\n/g, '').replace(/ {2}/g, ' ') if (inspected.length > shorten) { inspected = inspected.slice(0, shorten) + '...' @@ -74,10 +75,10 @@ export function createRPCServer( msg = `${request.method}${batchAddOn} responded with:\n${inspectParams(response)}` } else { msg = `${request.method}${batchAddOn} responded with: ` - if (response.result) { + if (isTruthy(response.result)) { msg += inspectParams(response, 125) } - if (response.error) { + if (isTruthy(response.error)) { msg += `error: ${response.error.message}` } } @@ -127,7 +128,7 @@ export function createRPCServer( ] const ethEngineSubsetMethods: { [key: string]: Function } = {} for (const method of ethMethodsToBeIncluded) { - if (ethMethods[method]) ethEngineSubsetMethods[method] = ethMethods[method] + if (isTruthy(ethMethods[method])) ethEngineSubsetMethods[method] = ethMethods[method] } methods = { ...ethEngineSubsetMethods, ...manager.getMethods(true) } break @@ -157,7 +158,7 @@ export function createRPCServerListener(opts: CreateRPCServerListenerOpts): Http const { server, withEngineMiddleware, rpcCors } = opts const app = Connect() - if (rpcCors) app.use(cors({ origin: rpcCors })) + if (isTruthy(rpcCors)) app.use(cors({ origin: rpcCors })) // GOSSIP_MAX_SIZE_BELLATRIX is proposed to be 10MiB app.use(jsonParser({ limit: '11mb' })) @@ -193,7 +194,7 @@ export function createWsRPCServerListener(opts: CreateWSServerOpts): HttpServer const app = Connect() // In case browser pre-flights the upgrade request with an options request // more likely in case of wss connection - if (rpcCors) app.use(cors({ origin: rpcCors })) + if (isTruthy(rpcCors)) app.use(cors({ origin: rpcCors })) httpServer = createServer(app) } diff --git a/packages/client/test/cli/cli-libp2p.spec.ts b/packages/client/test/cli/cli-libp2p.spec.ts index dda5b43f38..30aefcdcbe 100644 --- a/packages/client/test/cli/cli-libp2p.spec.ts +++ b/packages/client/test/cli/cli-libp2p.spec.ts @@ -27,7 +27,7 @@ tape('[CLI] rpc', (t) => { const hasEnded = false child.stdout.on('data', async (data) => { - const message = data.toString() + const message: string = data.toString() if (message.includes('transport=libp2p')) { st.pass('libp2p server started') @@ -50,7 +50,7 @@ tape('[CLI] rpc', (t) => { ], ]) child2.stdout.on('data', async (data) => { - const message = data.toString() + const message: string = data.toString() if (message.includes('Peer added')) { st.pass('connected to peer over libp2p') child2.kill('SIGINT') @@ -62,13 +62,13 @@ tape('[CLI] rpc', (t) => { }) child.stderr.on('data', (data) => { - const message = data.toString() + const message: string = data.toString() st.fail(`stderr: ${message}`) end(child, hasEnded, st) }) child.on('close', (code) => { - if (code && code > 0) { + if (typeof code === 'number' && code > 0) { st.fail(`child process exited with code ${code}`) end(child, hasEnded, st) } diff --git a/packages/client/test/cli/cli-rpc.spec.ts b/packages/client/test/cli/cli-rpc.spec.ts index 242d152e59..616f22b8d9 100644 --- a/packages/client/test/cli/cli-rpc.spec.ts +++ b/packages/client/test/cli/cli-rpc.spec.ts @@ -21,7 +21,7 @@ tape('[CLI] rpc', (t) => { const hasEnded = false child.stdout.on('data', async (data) => { - const message = data.toString() + const message: string = data.toString() if (message.includes('http://')) { // if http endpoint startup message detected, call http endpoint with RPC method const client = Client.http({ port: 8545 }) @@ -42,13 +42,13 @@ tape('[CLI] rpc', (t) => { }) child.stderr.on('data', (data) => { - const message = data.toString() + const message: string = data.toString() st.fail(`stderr: ${message}`) end(child, hasEnded, st) }) child.on('close', (code) => { - if (code && code > 0) { + if (typeof code === 'number' && code > 0) { st.fail(`child process exited with code ${code}`) end(child, hasEnded, st) } @@ -62,7 +62,7 @@ tape('[CLI] rpc', (t) => { const hasEnded = false child.stdout.on('data', async (data) => { - const message = data.toString() + const message: string = data.toString() if (message.includes('address=http://')) { st.fail('http endpoint should not be enabled') } @@ -76,13 +76,13 @@ tape('[CLI] rpc', (t) => { }) child.stderr.on('data', (data) => { - const message = data.toString() + const message: string = data.toString() st.fail(`stderr: ${message}`) end(child, hasEnded, st) }) child.on('close', (code) => { - if (code && code > 0) { + if (typeof code === 'number' && code > 0) { st.fail(`child process exited with code ${code}`) end(child, hasEnded, st) } diff --git a/packages/client/test/cli/cli-sync.spec.ts b/packages/client/test/cli/cli-sync.spec.ts index eb155a77f2..0b51d85e08 100644 --- a/packages/client/test/cli/cli-sync.spec.ts +++ b/packages/client/test/cli/cli-sync.spec.ts @@ -22,7 +22,7 @@ tape('[CLI] sync', (t) => { } child.stdout.on('data', (data) => { - const message = data.toString() + const message: string = data.toString() // log message for easier debugging // eslint-disable-next-line no-console @@ -39,7 +39,7 @@ tape('[CLI] sync', (t) => { }) child.stderr.on('data', (data) => { - const message = data.toString() + const message: string = data.toString() if (message.includes('Possible EventEmitter memory leak detected')) { // This is okay. return @@ -49,7 +49,7 @@ tape('[CLI] sync', (t) => { }) child.on('close', (code) => { - if (code && code > 0) { + if (typeof code === 'number' && code > 0) { st.fail(`child process exited with code ${code}`) end() } diff --git a/packages/client/test/integration/merge.spec.ts b/packages/client/test/integration/merge.spec.ts index e101431ac0..bffe1dbae8 100644 --- a/packages/client/test/integration/merge.spec.ts +++ b/packages/client/test/integration/merge.spec.ts @@ -7,7 +7,7 @@ import { ConsensusAlgorithm, Hardfork, } from '@ethereumjs/common' -import { Address } from '@ethereumjs/util' +import { Address, isFalsy, isTruthy } from '@ethereumjs/util' import { Config } from '../../lib/config' import { Chain } from '../../lib/blockchain' import { FullEthereumService } from '../../lib/service' @@ -141,7 +141,7 @@ tape('[Integration:Merge]', async (t) => { remoteService.config.events.on(Event.CHAIN_UPDATED, async () => { const { height, td } = remoteService.chain.headers if (td > targetTTD) { - if (!terminalHeight) { + if (isFalsy(terminalHeight)) { terminalHeight = height } t.equal( @@ -155,7 +155,7 @@ tape('[Integration:Merge]', async (t) => { await destroy(remoteServer, remoteService) t.end() } - if (terminalHeight && terminalHeight < height) { + if (isTruthy(terminalHeight) && terminalHeight < height) { t.fail('chain should not exceed merge terminal block') } }) diff --git a/packages/client/test/integration/mocks/mockpeer.ts b/packages/client/test/integration/mocks/mockpeer.ts index e898b2c4c5..355cdcf1b5 100644 --- a/packages/client/test/integration/mocks/mockpeer.ts +++ b/packages/client/test/integration/mocks/mockpeer.ts @@ -63,7 +63,7 @@ export class MockPeer extends Peer { }) await Promise.all( this.protocols.map(async (p) => { - if (!stream.protocols.includes(`${p.name}/${p.versions[0]}`)) return + if (!(stream.protocols as string[]).includes(`${p.name}/${p.versions[0]}`)) return await p.open() await this.bindProtocol(p, new MockSender(p.name, pushableFn, receiver)) }) diff --git a/packages/client/test/integration/mocks/mockserver.ts b/packages/client/test/integration/mocks/mockserver.ts index c5ca7bc3f0..3c2c5e12f7 100644 --- a/packages/client/test/integration/mocks/mockserver.ts +++ b/packages/client/test/integration/mocks/mockserver.ts @@ -1,3 +1,4 @@ +import { isTruthy } from '@ethereumjs/util' import { Server, ServerOptions } from '../../../lib/net/server' import { Event } from '../../../lib/types' import { MockPeer } from './mockpeer' @@ -45,7 +46,7 @@ export class MockServer extends Server { // This wait is essential to clear out the pending setTimeout in the // createStream in ./network.ts await this.wait(20) - while (servers[this.location]) { + while (isTruthy(servers[this.location])) { await destroyServer(this.location) } await super.stop() @@ -84,7 +85,7 @@ export class MockServer extends Server { disconnect(id: string) { const peer = this.peers[id] - if (peer) this.config.events.emit(Event.PEER_DISCONNECTED, peer) + if (isTruthy(peer)) this.config.events.emit(Event.PEER_DISCONNECTED, peer) } async wait(delay?: number) { diff --git a/packages/client/test/integration/mocks/network.ts b/packages/client/test/integration/mocks/network.ts index cc40429c9a..7a7c13adb2 100644 --- a/packages/client/test/integration/mocks/network.ts +++ b/packages/client/test/integration/mocks/network.ts @@ -1,3 +1,4 @@ +import { isFalsy, isTruthy } from '@ethereumjs/util' import { EventEmitter } from 'events' const DuplexPair = require('it-pair/duplex') @@ -24,7 +25,7 @@ interface ServerDetails { export const servers: ServerDetails = {} export function createServer(location: string) { - if (servers[location]) { + if (isTruthy(servers[location])) { throw new Error(`Already running a server at ${location}`) } servers[location] = { @@ -37,9 +38,9 @@ export function createServer(location: string) { } export function destroyStream(id: string, location: string) { - if (servers[location]) { + if (isTruthy(servers[location])) { const stream = servers[location].streams[id] - if (stream) { + if (isTruthy(stream)) { delete servers[location].streams[id] } } @@ -56,7 +57,7 @@ export async function destroyServer(location: string) { } export function createStream(id: string, location: string, protocols: string[]) { - if (!servers[location]) { + if (isFalsy(servers[location])) { throw new Error(`There is no server at ${location}`) } const stream = Stream(protocols) diff --git a/packages/client/test/logging.spec.ts b/packages/client/test/logging.spec.ts index cea4e374a0..543becb65d 100644 --- a/packages/client/test/logging.spec.ts +++ b/packages/client/test/logging.spec.ts @@ -1,3 +1,4 @@ +import { isTruthy } from '@ethereumjs/util' import * as tape from 'tape' import { getLogger } from '../lib/logging' @@ -23,7 +24,7 @@ tape('[Logging]', (t) => { }) t.test('should colorize key=value pairs', (st) => { - if (process.env.GITHUB_ACTION) { + if (isTruthy(process.env.GITHUB_ACTION)) { st.skip('no color functionality in ci') return st.end() } diff --git a/packages/client/test/rpc/admin/nodeInfo.spec.ts b/packages/client/test/rpc/admin/nodeInfo.spec.ts index 470ac00d9b..f45ffcc155 100644 --- a/packages/client/test/rpc/admin/nodeInfo.spec.ts +++ b/packages/client/test/rpc/admin/nodeInfo.spec.ts @@ -1,3 +1,4 @@ +import { isTruthy } from '@ethereumjs/util' import * as tape from 'tape' import { startRPC, createManager, createClient, params, baseRequest } from '../helpers' @@ -11,7 +12,7 @@ tape(method, async (t) => { const expectRes = (res: any) => { const { result } = res.body - if (result) { + if (isTruthy(result)) { t.pass('admin_nodeInfo returns a value') } else { throw new Error('no return value') diff --git a/packages/client/test/rpc/eth/getLogs.spec.ts b/packages/client/test/rpc/eth/getLogs.spec.ts index 57195d7bb6..fc2a769857 100644 --- a/packages/client/test/rpc/eth/getLogs.spec.ts +++ b/packages/client/test/rpc/eth/getLogs.spec.ts @@ -116,7 +116,7 @@ tape(`${method}: call with valid arguments`, async (t) => { const msg = 'should return the correct logs (filter by single address)' if ( res.body.result.length === 10 && - res.body.result.every((r: any) => r.address === contractAddr1.toString()) + res.body.result.every((r: any) => r.address === contractAddr1.toString()) === true ) { t.pass(msg) } else { @@ -132,7 +132,7 @@ tape(`${method}: call with valid arguments`, async (t) => { const msg = 'should return the correct logs (filter by multiple addresses)' if ( res.body.result.length === 20 && - res.body.result.every((r: any) => addresses.includes(r.address)) + res.body.result.every((r: any) => addresses.includes(r.address)) === true ) { t.pass(msg) } else { diff --git a/packages/client/test/rpc/helpers.ts b/packages/client/test/rpc/helpers.ts index 5073c09074..37d67b215f 100644 --- a/packages/client/test/rpc/helpers.ts +++ b/packages/client/test/rpc/helpers.ts @@ -3,7 +3,7 @@ import { Server as RPCServer, HttpServer } from 'jayson/promise' import { BlockHeader } from '@ethereumjs/block' import { Blockchain } from '@ethereumjs/blockchain' import { Chain as ChainEnum, Common } from '@ethereumjs/common' -import { Address } from '@ethereumjs/util' +import { Address, isTruthy } from '@ethereumjs/util' import { RPCManager as Manager } from '../../lib/rpc' import { getLogger } from '../../lib/logging' import { Config } from '../../lib/config' @@ -35,11 +35,11 @@ export function startRPC( ) { const { port, wsServer } = opts const server = new RPCServer(methods) - const httpServer = wsServer + const httpServer = isTruthy(wsServer) ? createWsRPCServerListener({ server, withEngineMiddleware }) : createRPCServerListener({ server, withEngineMiddleware }) if (!httpServer) throw Error('Could not create server') - if (port) httpServer.listen(port) + if (isTruthy(port)) httpServer.listen(port) return httpServer } @@ -71,7 +71,7 @@ export function createClient(clientOpts: any = {}) { const clientConfig = { ...defaultClientConfig, ...clientOpts } chain.getTd = async (_hash: Buffer, _num: bigint) => BigInt(1000) - if (chain._headers) { + if (isTruthy(chain._headers)) { chain._headers.latest = BlockHeader.fromHeaderData({}, { common }) } @@ -98,8 +98,8 @@ export function createClient(clientOpts: any = {}) { } let execution - if (clientOpts.includeVM) { - const metaDB: any = clientOpts.enableMetaDB ? new MemoryLevel() : undefined + if (isTruthy(clientOpts.includeVM)) { + const metaDB: any = isTruthy(clientOpts.enableMetaDB) ? new MemoryLevel() : undefined execution = new VMExecution({ config, chain, metaDB }) } @@ -137,7 +137,7 @@ export function createClient(clientOpts: any = {}) { }, } - if (clientOpts.includeVM) { + if (isTruthy(clientOpts.includeVM)) { client.services[0].txPool = new TxPool({ config, service: client.services[0] }) } diff --git a/packages/client/test/rpc/rpc.spec.ts b/packages/client/test/rpc/rpc.spec.ts index 8731c265e8..2d9dd1523d 100644 --- a/packages/client/test/rpc/rpc.spec.ts +++ b/packages/client/test/rpc/rpc.spec.ts @@ -2,6 +2,7 @@ import * as tape from 'tape' import { encode, TAlgorithm } from 'jwt-simple' import { startRPC, closeRPC } from './helpers' import { METHOD_NOT_FOUND } from '../../lib/rpc/error-code' +import { isFalsy } from '@ethereumjs/util' const request = require('supertest') const jwtSecret = Buffer.from(Array.from({ length: 32 }, () => Math.round(Math.random() * 255))) @@ -128,7 +129,7 @@ tape('call JSON RPC with nonexistent method', (t) => { .set('Content-Type', 'application/json') .send(req) .expect((res: any) => { - if (!res.body.error) { + if (isFalsy(res.body.error)) { throw new Error('should return an error object') } if (res.body.error.code !== METHOD_NOT_FOUND) { @@ -168,7 +169,7 @@ tape('call JSON-RPC auth protected server with unprotected method without token' tape('call JSON-RPC auth protected server with protected method without token', (t) => { const server = startRPC({}, undefined, { jwtSecret, - unlessFn: (req: any) => !req.body.method.includes('protected_'), + unlessFn: (req: any) => !(req.body.method as string).includes('protected_'), }) const req = { @@ -192,7 +193,7 @@ tape('call JSON-RPC auth protected server with protected method without token', tape('call JSON-RPC auth protected server with protected method with token', (t) => { const server = startRPC({}, undefined, { jwtSecret, - unlessFn: (req: any) => !req.body.method.includes('protected_'), + unlessFn: (req: any) => !(req.body.method as string).includes('protected_'), }) const req = { diff --git a/packages/client/test/rpc/util.ts b/packages/client/test/rpc/util.ts index b5f827de2b..ea73826938 100644 --- a/packages/client/test/rpc/util.ts +++ b/packages/client/test/rpc/util.ts @@ -1,14 +1,18 @@ +import { isFalsy, isTruthy } from '@ethereumjs/util' import * as tape from 'tape' -export function checkError(t: tape.Test, expectedCode: any, expectedMessage?: any) { +export function checkError(t: tape.Test, expectedCode: number, expectedMessage?: string) { return (res: any) => { - if (!res.body.error) { + if (isFalsy(res.body.error)) { throw new Error('should return an error object') } if (res.body.error.code !== expectedCode) { throw new Error(`should have an error code ${expectedCode}, got ${res.body.error.code}`) } - if (expectedMessage && !res.body.error.message.includes(expectedMessage)) { + if ( + isTruthy(expectedMessage) && + !(res.body.error.message as string).includes(expectedMessage) + ) { throw new Error( `should have an error message "${expectedMessage}", got "${res.body.error.message}"` ) diff --git a/packages/client/test/rpc/util/CLConnectionManager.spec.ts b/packages/client/test/rpc/util/CLConnectionManager.spec.ts index 8365f54481..63bd7c0a75 100644 --- a/packages/client/test/rpc/util/CLConnectionManager.spec.ts +++ b/packages/client/test/rpc/util/CLConnectionManager.spec.ts @@ -76,10 +76,10 @@ tape('[CLConnectionManager]', (t) => { const config = new Config() const manager = new CLConnectionManager({ config: config }) config.logger.on('data', (chunk) => { - if (chunk.message.includes('consensus forkchoice update head=0x67b9')) { + if ((chunk.message as string).includes('consensus forkchoice update head=0x67b9')) { st.pass('received last fork choice message') } - if (chunk.message.includes('consensus payload received number=55504')) { + if ((chunk.message as string).includes('consensus payload received number=55504')) { st.pass('received last payload message') manager.stop() config.logger.removeAllListeners() diff --git a/packages/client/test/sync/lightsync.spec.ts b/packages/client/test/sync/lightsync.spec.ts index 7e4097f80b..64aea9cbfb 100644 --- a/packages/client/test/sync/lightsync.spec.ts +++ b/packages/client/test/sync/lightsync.spec.ts @@ -119,7 +119,7 @@ tape('[LightSynchronizer]', async (t) => { config.events.emit(Event.SYNC_FETCHED_HEADERS, [BlockHeader.fromHeaderData({})]) ) config.logger.on('data', async (data) => { - if (data.message.includes('Imported headers count=1')) { + if ((data.message as string).includes('Imported headers count=1')) { st.pass('successfully imported new header') config.logger.removeAllListeners() await sync.stop() @@ -153,7 +153,7 @@ tape('[LightSynchronizer]', async (t) => { config.events.emit(Event.SYNC_FETCHED_HEADERS, [] as BlockHeader[]) ) config.logger.on('data', async (data) => { - if (data.message.includes('No headers fetched are applicable for import')) { + if ((data.message as string).includes('No headers fetched are applicable for import')) { st.pass('generated correct warning message when no headers received') config.logger.removeAllListeners() await sync.stop() diff --git a/packages/client/test/sync/skeleton.spec.ts b/packages/client/test/sync/skeleton.spec.ts index 6a3b772b04..8c81381aa8 100644 --- a/packages/client/test/sync/skeleton.spec.ts +++ b/packages/client/test/sync/skeleton.spec.ts @@ -269,7 +269,10 @@ tape('[Skeleton]', async (t) => { st.pass(`test ${testCaseIndex}: successfully passed`) } } catch (error: any) { - if (error.message.includes(testCase.err?.message)) { + if ( + typeof testCase.err?.message === 'string' && + (error.message as string).includes(testCase.err.message) + ) { st.pass(`test ${testCaseIndex}: passed with correct error`) } else { st.fail(`test ${testCaseIndex}: received wrong error`) diff --git a/packages/client/test/sync/txpool.spec.ts b/packages/client/test/sync/txpool.spec.ts index c06b4f1c4b..1321f0becd 100644 --- a/packages/client/test/sync/txpool.spec.ts +++ b/packages/client/test/sync/txpool.spec.ts @@ -2,7 +2,8 @@ import * as tape from 'tape' import { Chain, Common, Hardfork } from '@ethereumjs/common' import { AccessListEIP2930Transaction, FeeMarketEIP1559Transaction } from '@ethereumjs/tx' import { Block } from '@ethereumjs/block' -import { Account, privateToAddress } from '@ethereumjs/util' +import { Account, isFalsy, isTruthy, privateToAddress } from '@ethereumjs/util' +import { StateManager } from '@ethereumjs/statemanager' import { PeerPool } from '../../lib/net/peerpool' import { TxPool } from '../../lib/service/txpool' import { Config } from '../../lib/config' @@ -27,12 +28,17 @@ const setup = () => { const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.London }) const config = new Config({ transports: [] }) -const handleTxs = async (txs: any[], failMessage: string, stateManager?: any, pool?: any) => { - if (!pool) { +const handleTxs = async ( + txs: any[], + failMessage: string, + stateManager?: StateManager, + pool?: TxPool +) => { + if (isFalsy(pool)) { pool = setup().pool } try { - if (stateManager) { + if (isTruthy(stateManager)) { ;(pool).service.execution.vm.stateManager = stateManager } @@ -64,7 +70,7 @@ const handleTxs = async (txs: any[], failMessage: string, stateManager?: any, po pool.stop() pool.close() // Return false if the error message contains the fail message - return !e.message.includes(failMessage) + return !(e.message as string).includes(failMessage) } } @@ -409,7 +415,7 @@ tape('[TxPool]', async (t) => { t.notOk( await handleTxs(txs, 'tx nonce too low', { getAccount: () => new Account(BigInt(1), BigInt('50000000000000000000')), - }), + } as any), 'successfully rejected tx with invalid nonce' ) }) @@ -429,7 +435,7 @@ tape('[TxPool]', async (t) => { t.notOk( await handleTxs(txs, 'exceeds the max data size', { getAccount: () => new Account(BigInt(0), BigInt('50000000000000000000000')), - }), + } as any), 'successfully rejected tx with too much data' ) }) @@ -449,7 +455,7 @@ tape('[TxPool]', async (t) => { t.notOk( await handleTxs(txs, 'insufficient balance', { getAccount: () => new Account(BigInt(0), BigInt('0')), - }), + } as any), 'successfully rejected account with too low balance' ) }) diff --git a/packages/client/test/util/rpc.spec.ts b/packages/client/test/util/rpc.spec.ts index 6465c845f2..f2cbbc1589 100644 --- a/packages/client/test/util/rpc.spec.ts +++ b/packages/client/test/util/rpc.spec.ts @@ -9,6 +9,7 @@ import { import { EthereumClient } from '../../lib/client' import { Config } from '../../lib/config' import { METHOD_NOT_FOUND } from '../../lib/rpc/error-code' +import { isTruthy } from '@ethereumjs/util' const request = require('supertest') tape('[Util/RPC]', (t) => { @@ -40,7 +41,7 @@ tape('[Util/RPC]', (t) => { server.emit('response', req, []) // empty server.emit('response', [req], respBulk) // mismatch length - st.ok(httpServer && wsServer, 'should return http and ws servers') + st.ok(isTruthy(httpServer) && isTruthy(wsServer), 'should return http and ws servers') } } st.end() @@ -80,7 +81,7 @@ tape('[Util/RPC/Engine eth methods]', async (t) => { .set('Content-Type', 'application/json') .send(req) .expect((res: any) => { - if (res.body.error && res.body.error.code === METHOD_NOT_FOUND) { + if (res.body.error?.code === METHOD_NOT_FOUND) { throw new Error(`should have an error code ${METHOD_NOT_FOUND}`) } }) diff --git a/packages/common/src/common.ts b/packages/common/src/common.ts index 5ef10e17a5..9023f2d25f 100644 --- a/packages/common/src/common.ts +++ b/packages/common/src/common.ts @@ -1,6 +1,6 @@ import { EventEmitter } from 'events' import { buf as crc32Buffer } from 'crc-32' -import { BigIntLike, toType, TypeOutput, intToBuffer } from '@ethereumjs/util' +import { BigIntLike, toType, TypeOutput, intToBuffer, isTruthy, isFalsy } from '@ethereumjs/util' import { hardforks as HARDFORK_CHANGES } from './hardforks' import { EIPs } from './eips' import { Hardfork, Chain, ConsensusAlgorithm, ConsensusType, CustomChain } from './enums' @@ -175,7 +175,7 @@ export class Common extends EventEmitter { throw new Error(`Chain with ID ${chain} not supported`) } - if (initializedChains[chain]) { + if (isTruthy(initializedChains[chain])) { return initializedChains[chain] as ChainConfig } @@ -188,7 +188,7 @@ export class Common extends EventEmitter { this._chainParams = this.setChain(opts.chain) this.DEFAULT_HARDFORK = this._chainParams.defaultHardfork ?? Hardfork.London this._hardfork = this.DEFAULT_HARDFORK - if (opts.hardfork) { + if (isTruthy(opts.hardfork)) { this.setHardfork(opts.hardfork) } if (opts.eips) { @@ -277,7 +277,7 @@ export class Common extends EventEmitter { if (blockNumber >= BigInt(hf.block)) { hardfork = hf.name as Hardfork } - if (td && hf.td) { + if (td && isTruthy(hf.td)) { if (td >= BigInt(hf.td)) { minTdHF = hf.name } else { @@ -288,14 +288,14 @@ export class Common extends EventEmitter { } if (td) { let msgAdd = `block number: ${blockNumber} (-> ${hardfork}), ` - if (minTdHF) { + if (isTruthy(minTdHF)) { if (!this.hardforkGteHardfork(hardfork, minTdHF)) { const msg = 'HF determined by block number is lower than the minimum total difficulty HF' msgAdd += `total difficulty: ${td} (-> ${minTdHF})` throw new Error(`${msg}: ${msgAdd}`) } } - if (maxTdHF) { + if (isTruthy(maxTdHF)) { if (!this.hardforkGteHardfork(maxTdHF, hardfork)) { const msg = 'Maximum HF determined by total difficulty is lower than the block number HF' msgAdd += `total difficulty: ${td} (-> ${maxTdHF})` @@ -352,7 +352,7 @@ export class Common extends EventEmitter { `${eip} cannot be activated on hardfork ${this.hardfork()}, minimumHardfork: ${minHF}` ) } - if (EIPs[eip].requiredEIPs) { + if (isTruthy(EIPs[eip].requiredEIPs)) { ;(EIPs[eip].requiredEIPs as number[]).forEach((elem) => { if (!(eips.includes(elem) || this.isActivatedEIP(elem))) { throw new Error(`${eip} requires EIP ${elem}, but is not included in the EIP list`) @@ -402,9 +402,9 @@ export class Common extends EventEmitter { const valueEIP = this.paramByEIP(topic, name, eip) value = valueEIP !== undefined ? valueEIP : value } - // Paramater-inlining HF file (e.g. istanbul.json) + // Parameter-inlining HF file (e.g. istanbul.json) } else { - if (!hfChanges[1][topic]) { + if (isFalsy(hfChanges[1][topic])) { throw new Error(`Topic ${topic} not defined`) } if (hfChanges[1][topic][name] !== undefined) { @@ -413,8 +413,7 @@ export class Common extends EventEmitter { } if (hfChanges[0] === hardfork) break } - if (!value) return BigInt(0) - return BigInt(value) + return BigInt(value ?? 0) } /** @@ -470,7 +469,7 @@ export class Common extends EventEmitter { for (const hfChanges of HARDFORK_CHANGES) { const hf = hfChanges[1] if (this.gteHardfork(hf['name']) && 'eips' in hf) { - if (hf['eips'].includes(eip)) { + if ((hf['eips'] as number[]).includes(eip)) { return true } } @@ -488,7 +487,7 @@ export class Common extends EventEmitter { blockNumber = toType(blockNumber, TypeOutput.BigInt) hardfork = hardfork ?? this._hardfork const hfBlock = this.hardforkBlock(hardfork) - if (hfBlock && blockNumber >= hfBlock) { + if (isTruthy(hfBlock) && blockNumber >= hfBlock) { return true } return false @@ -572,7 +571,7 @@ export class Common extends EventEmitter { blockNumber = toType(blockNumber, TypeOutput.BigInt) hardfork = hardfork ?? this._hardfork const block = this.hardforkBlock(hardfork) - return block ? block === blockNumber : false + return isTruthy(block) ? block === blockNumber : false } /** @@ -762,10 +761,7 @@ export class Common extends EventEmitter { } if (hfChanges[0] === hardfork) break } - if (value) { - return value - } - return this._chainParams['consensus']!['type'] + return value ?? this._chainParams['consensus']['type'] } /** @@ -787,10 +783,9 @@ export class Common extends EventEmitter { } if (hfChanges[0] === hardfork) break } - if (value) { - return value - } - return this._chainParams['consensus']!['algorithm'] as ConsensusAlgorithm + return isTruthy(value) + ? value + : (this._chainParams['consensus']['algorithm'] as ConsensusAlgorithm) } /** @@ -818,11 +813,9 @@ export class Common extends EventEmitter { } if (hfChanges[0] === hardfork) break } - if (value) { - return value - } - const consensusAlgorithm = this.consensusAlgorithm() - return this._chainParams['consensus']![consensusAlgorithm as ConsensusAlgorithm]! + return isTruthy(value) + ? value + : this._chainParams['consensus'][this.consensusAlgorithm() as ConsensusAlgorithm]! } /** diff --git a/packages/common/tests/hardforks.spec.ts b/packages/common/tests/hardforks.spec.ts index 1faf7c1875..753fe0ea85 100644 --- a/packages/common/tests/hardforks.spec.ts +++ b/packages/common/tests/hardforks.spec.ts @@ -278,7 +278,7 @@ tape('[Common]: Hardfork logic', function (t: tape.Test) { for (const [chain, genesisHash] of chains) { c = new Common({ chain }) for (const hf of c.hardforks()) { - if (hf.forkHash && hf.forkHash !== null) { + if (typeof hf.forkHash === 'string') { const msg = `Verify forkHash calculation for: ${Chain[chain]} -> ${hf.name}` st.equal(c._calcForkHash(hf.name, genesisHash), hf.forkHash, msg) } diff --git a/packages/devp2p/examples/peer-communication-les.ts b/packages/devp2p/examples/peer-communication-les.ts index 7d90c3e4f8..e3c7a6e5ca 100644 --- a/packages/devp2p/examples/peer-communication-les.ts +++ b/packages/devp2p/examples/peer-communication-les.ts @@ -6,6 +6,7 @@ import { Block, BlockHeader } from '@ethereumjs/block' import ms from 'ms' import chalk from 'chalk' import { randomBytes } from 'crypto' +import { isTruthy } from '@ethereumjs/util' const PRIVATE_KEY = randomBytes(32) @@ -63,7 +64,9 @@ const rlpx = new devp2p.RLPx(PRIVATE_KEY, { remoteClientIdFilter: REMOTE_CLIENTID_FILTER, }) -rlpx.on('error', (err) => console.error(chalk.red(`RLPx error: ${err.stack || err}`))) +rlpx.on('error', (err) => + console.error(chalk.red(`RLPx error: ${isTruthy(err.stack) ? err.stack : err}`)) +) rlpx.on('peer:added', (peer) => { const addr = getPeerAddr(peer) @@ -146,7 +149,7 @@ rlpx.on('peer:added', (peer) => { }) rlpx.on('peer:removed', (peer, reasonCode, disconnectWe) => { - const who = disconnectWe ? 'we disconnect' : 'peer disconnect' + const who = isTruthy(disconnectWe) ? 'we disconnect' : 'peer disconnect' const total = rlpx.getPeers().length console.log( chalk.yellow( @@ -168,7 +171,9 @@ rlpx.on('peer:error', (peer, err) => { return } - console.error(chalk.red(`Peer error (${getPeerAddr(peer)}): ${err.stack || err}`)) + console.error( + chalk.red(`Peer error (${getPeerAddr(peer)}): ${isTruthy(err.stack) ? err.stack : err}`) + ) }) // uncomment, if you want accept incoming connections @@ -177,7 +182,7 @@ rlpx.on('peer:error', (peer, err) => { for (const bootnode of BOOTNODES) { dpt.bootstrap(bootnode).catch((err) => { - console.error(chalk.bold.red(`DPT bootstrap error: ${err.stack || err}`)) + console.error(chalk.bold.red(`DPT bootstrap error: ${isTruthy(err.stack) ? err.stack : err}`)) }) } @@ -192,7 +197,7 @@ dpt.addPeer({ address: '127.0.0.1', udpPort: 30303, tcpPort: 30303 }) udpPort: peer.tcpPort }) }) - .catch((err) => console.log(`error on connection to local node: ${err.stack || err}`)) */ + .catch((err) => console.log(`error on connection to local node: ${isTruthy(err.stack) ? err.stack : err}`)) */ function onNewBlock(block: Block, peer: Peer) { const blockHashHex = block.hash().toString('hex') diff --git a/packages/devp2p/examples/peer-communication.ts b/packages/devp2p/examples/peer-communication.ts index 2bac7ffe5d..18218793b1 100644 --- a/packages/devp2p/examples/peer-communication.ts +++ b/packages/devp2p/examples/peer-communication.ts @@ -5,7 +5,7 @@ import chalk from 'chalk' import { Chain, Common, Hardfork } from '@ethereumjs/common' import { TypedTransaction, TransactionFactory } from '@ethereumjs/tx' import { Block, BlockHeader } from '@ethereumjs/block' -import { arrToBufArr } from '@ethereumjs/util' +import { arrToBufArr, isTruthy } from '@ethereumjs/util' import { RLP } from 'rlp' import * as devp2p from '../src/index' import { ETH, Peer } from '../src/index' @@ -68,7 +68,9 @@ const rlpx = new devp2p.RLPx(PRIVATE_KEY, { remoteClientIdFilter: REMOTE_CLIENTID_FILTER, }) -rlpx.on('error', (err) => console.error(chalk.red(`RLPx error: ${err.stack || err}`))) +rlpx.on('error', (err) => + console.error(chalk.red(`RLPx error: ${isTruthy(err.stack) ? err.stack : err}`)) +) rlpx.on('peer:added', (peer) => { const addr = getPeerAddr(peer) @@ -286,7 +288,7 @@ rlpx.on('peer:added', (peer) => { }) rlpx.on('peer:removed', (peer, reasonCode, disconnectWe) => { - const who = disconnectWe ? 'we disconnect' : 'peer disconnect' + const who = isTruthy(disconnectWe) ? 'we disconnect' : 'peer disconnect' const total = rlpx.getPeers().length console.log( chalk.yellow( @@ -308,7 +310,9 @@ rlpx.on('peer:error', (peer, err) => { return } - console.error(chalk.red(`Peer error (${getPeerAddr(peer)}): ${err.stack || err}`)) + console.error( + chalk.red(`Peer error (${getPeerAddr(peer)}): ${isTruthy(err.stack) ? err.stack : err}`) + ) }) // uncomment, if you want accept incoming connections @@ -317,7 +321,7 @@ rlpx.on('peer:error', (peer, err) => { for (const bootnode of BOOTNODES) { dpt.bootstrap(bootnode).catch((err) => { - console.error(chalk.bold.red(`DPT bootstrap error: ${err.stack || err}`)) + console.error(chalk.bold.red(`DPT bootstrap error: ${isTruthy(err.stack) ? err.stack : err}`)) }) } @@ -332,7 +336,7 @@ dpt.addPeer({ address: '127.0.0.1', udpPort: 30303, tcpPort: 30303 }) udpPort: peer.tcpPort }) }) - .catch((err) => console.log(`error on connection to local node: ${err.stack || err}`)) + .catch((err) => console.log(`error on connection to local node: ${isTruthy(err.stack) ? err.stack : err}`)) */ const txCache = new LRUCache({ max: 1000 }) diff --git a/packages/devp2p/examples/simple.ts b/packages/devp2p/examples/simple.ts index ad0f07afce..1981e32b20 100644 --- a/packages/devp2p/examples/simple.ts +++ b/packages/devp2p/examples/simple.ts @@ -1,6 +1,7 @@ import chalk from 'chalk' import { Chain, Common } from '@ethereumjs/common' import { DPT } from '../src/index' +import { isTruthy } from '@ethereumjs/util' const PRIVATE_KEY = 'd772e3d6a001a38064dd23964dd2836239fa0e6cec8b28972a87460a17210fe9' @@ -23,7 +24,7 @@ const dpt = new DPT(Buffer.from(PRIVATE_KEY, 'hex'), { }) /* eslint-disable no-console */ -dpt.on('error', (err) => console.error(chalk.red(err.stack || err))) +dpt.on('error', (err) => console.error(chalk.red(isTruthy(err.stack) ? err.stack : err))) dpt.on('peer:added', (peer) => { const info = `(${peer.id.toString('hex')},${peer.address},${peer.udpPort},${peer.tcpPort})` @@ -40,5 +41,7 @@ dpt.on('peer:removed', (peer) => { // dpt.bind(30303, '0.0.0.0') for (const bootnode of BOOTNODES) { - dpt.bootstrap(bootnode).catch((err) => console.error(chalk.bold.red(err.stack || err))) + dpt + .bootstrap(bootnode) + .catch((err) => console.error(chalk.bold.red(isTruthy(err.stack) ? err.stack : err))) } diff --git a/packages/devp2p/src/dns/dns.ts b/packages/devp2p/src/dns/dns.ts index f37206c411..44c93e7aa8 100644 --- a/packages/devp2p/src/dns/dns.ts +++ b/packages/devp2p/src/dns/dns.ts @@ -1,6 +1,7 @@ import { PeerInfo } from '../dpt' import { ENR } from './enr' import { debug as createDebugLogger } from 'debug' +import { isFalsy, isTruthy } from '@ethereumjs/util' let dns: any try { @@ -34,7 +35,7 @@ export class DNS { constructor(options: DNSOptions = {}) { this._DNSTreeCache = {} - if (options.dnsServerAddress) { + if (isTruthy(options.dnsServerAddress)) { dns.setServers([options.dnsServerAddress]) } } @@ -173,8 +174,9 @@ export class DNS { const response = await dns.promises.resolve(location, 'TXT') - if (!response.length) throw new Error('Received empty result array while fetching TXT record') - if (!response[0].length) throw new Error('Received empty TXT record') + if (response.length === 0) + throw new Error('Received empty result array while fetching TXT record') + if (response[0].length === 0) throw new Error('Received empty TXT record') // Branch entries can be an array of strings of comma delimited subdomains, with // some subdomain strings split across the array elements // (e.g btw end of arr[0] and beginning of arr[1]) @@ -194,7 +196,7 @@ export class DNS { * @return {boolean} */ private _isNewPeer(peer: PeerInfo | null, peers: PeerInfo[]): boolean { - if (!peer || !peer!.address) return false + if (isFalsy(peer) || isFalsy(peer.address)) return false for (const existingPeer of peers) { if (peer.address === existingPeer.address) { diff --git a/packages/devp2p/src/dpt/kbucket.ts b/packages/devp2p/src/dpt/kbucket.ts index 24d4e6f170..2361baca3d 100644 --- a/packages/devp2p/src/dpt/kbucket.ts +++ b/packages/devp2p/src/dpt/kbucket.ts @@ -1,3 +1,4 @@ +import { isTruthy } from '@ethereumjs/util' import { EventEmitter } from 'events' import _KBucket = require('k-bucket') import { PeerInfo } from './dpt' @@ -43,7 +44,7 @@ export class KBucket extends EventEmitter { const keys = [] if (Buffer.isBuffer(obj.id)) keys.push(obj.id.toString('hex')) - if (obj.address && obj.tcpPort) keys.push(`${obj.address}:${obj.tcpPort}`) + if (isTruthy(obj.address) && isTruthy(obj.tcpPort)) keys.push(`${obj.address}:${obj.tcpPort}`) return keys } diff --git a/packages/devp2p/src/dpt/server.ts b/packages/devp2p/src/dpt/server.ts index b4bb89243c..a037b4cdef 100644 --- a/packages/devp2p/src/dpt/server.ts +++ b/packages/devp2p/src/dpt/server.ts @@ -7,6 +7,7 @@ import { encode, decode } from './message' import { keccak256, pk2id, createDeferred, formatLogId, devp2pDebug } from '../util' import { DPT, PeerInfo } from './dpt' import { Socket as DgramSocket, RemoteInfo } from 'dgram' +import { isTruthy } from '@ethereumjs/util' const DEBUG_BASE_NAME = 'dpt:server' const verbose = createDebugLogger('verbose').enabled @@ -159,7 +160,7 @@ export class Server extends EventEmitter { } }, this._timeout) } - if (this._socket && peer.udpPort) + if (this._socket && isTruthy(peer.udpPort)) this._socket.send(msg, 0, msg.length, peer.udpPort, peer.address) return msg.slice(0, 32) // message id } @@ -199,12 +200,12 @@ export class Server extends EventEmitter { case 'pong': { let rkey = info.data.hash.toString('hex') const rkeyParity = this._parityRequestMap.get(rkey) - if (rkeyParity) { + if (isTruthy(rkeyParity)) { rkey = rkeyParity this._parityRequestMap.delete(rkeyParity) } const request = this._requests.get(rkey) - if (request) { + if (isTruthy(request)) { this._requests.delete(rkey) request.deferred.resolve({ id: peerId, diff --git a/packages/devp2p/src/protocol/eth.ts b/packages/devp2p/src/protocol/eth.ts index 8d64114d48..fa81664bf3 100644 --- a/packages/devp2p/src/protocol/eth.ts +++ b/packages/devp2p/src/protocol/eth.ts @@ -5,6 +5,7 @@ import { bufArrToArr, bufferToBigInt, bufferToHex, + isTruthy, } from '@ethereumjs/util' import { RLP } from 'rlp' import { int2buffer, buffer2int, assertEq, formatLogId, formatLogData } from '../util' @@ -27,7 +28,7 @@ export class ETH extends Protocol { // Set forkHash and nextForkBlock if (this._version >= 64) { const c = this._peer._common - this._hardfork = c.hardfork() ? c.hardfork() : this._hardfork + this._hardfork = isTruthy(c.hardfork()) ? c.hardfork() : this._hardfork // Set latestBlock minimally to start block of fork to have some more // accurate basis if no latestBlock is provided along status send this._latestBlock = c.hardforkBlock(this._hardfork) ?? BigInt(0) @@ -62,7 +63,9 @@ export class ETH extends Protocol { 'STATUS' ) this._peerStatus = payload as ETH.StatusMsg - const peerStatusMsg = `${this._peerStatus ? this._getStatusString(this._peerStatus) : ''}` + const peerStatusMsg = `${ + isTruthy(this._peerStatus) ? this._getStatusString(this._peerStatus) : '' + }` this.debug(messageName, `${debugMsg}: ${peerStatusMsg}`) this._handleStatus() break @@ -125,9 +128,13 @@ export class ETH extends Protocol { throw new Error(msg) } - if (!c.hardforkGteHardfork(peerFork.name, this._hardfork)) { + if (c.hardforkGteHardfork(peerFork.name, this._hardfork) === false) { const nextHardforkBlock = c.nextHardforkBlock(peerFork.name) - if (peerNextFork === null || !nextHardforkBlock || nextHardforkBlock !== peerNextFork) { + if ( + peerNextFork === null || + nextHardforkBlock === null || + nextHardforkBlock !== peerNextFork + ) { const msg = 'Outdated fork status, remote needs software update' this.debug('STATUS', msg) throw new Error(msg) @@ -207,7 +214,9 @@ export class ETH extends Protocol { this._verbose )}` if (this._version >= 64) { - sStr += `, ForkHash: ${status[5] ? '0x' + (status[5][0] as Buffer).toString('hex') : '-'}` + sStr += `, ForkHash: ${ + isTruthy(status[5]) ? '0x' + (status[5][0] as Buffer).toString('hex') : '-' + }` sStr += `, ForkNext: ${ (status[5][1] as Buffer).length > 0 ? buffer2int(status[5][1] as Buffer) : '-' }` @@ -255,7 +264,11 @@ export class ETH extends Protocol { let payload = Buffer.from(RLP.encode(bufArrToArr(this._status))) // Use snappy compression if peer supports DevP2P >=v5 - if (this._peer._hello?.protocolVersion && this._peer._hello?.protocolVersion >= 5) { + if ( + isTruthy(this._peer._hello) && + isTruthy(this._peer._hello.protocolVersion) && + this._peer._hello.protocolVersion >= 5 + ) { payload = snappy.compress(payload) } @@ -307,7 +320,11 @@ export class ETH extends Protocol { payload = Buffer.from(RLP.encode(bufArrToArr(payload))) // Use snappy compression if peer supports DevP2P >=v5 - if (this._peer._hello?.protocolVersion && this._peer._hello?.protocolVersion >= 5) { + if ( + isTruthy(this._peer._hello) && + isTruthy(this._peer._hello.protocolVersion) && + this._peer._hello?.protocolVersion >= 5 + ) { payload = snappy.compress(payload) } diff --git a/packages/devp2p/src/protocol/les.ts b/packages/devp2p/src/protocol/les.ts index 982bc909ab..34b919ba49 100644 --- a/packages/devp2p/src/protocol/les.ts +++ b/packages/devp2p/src/protocol/les.ts @@ -1,4 +1,4 @@ -import { arrToBufArr, bigIntToBuffer, bufArrToArr } from '@ethereumjs/util' +import { arrToBufArr, bigIntToBuffer, bufArrToArr, isFalsy, isTruthy } from '@ethereumjs/util' import { RLP } from 'rlp' import ms = require('ms') import * as snappy from 'snappyjs' @@ -131,18 +131,20 @@ export class LES extends Protocol { )}, ` sStr += `HeadH:${status['headHash'].toString('hex')}, HeadN:${buffer2int(status['headNum'])}, ` sStr += `GenH:${status['genesisHash'].toString('hex')}` - if (status['serveHeaders']) sStr += `, serveHeaders active` - if (status['serveChainSince']) sStr += `, ServeCS: ${buffer2int(status['serveChainSince'])}` - if (status['serveStateSince']) sStr += `, ServeSS: ${buffer2int(status['serveStateSince'])}` - if (status['txRelay']) sStr += `, txRelay active` - if (status['flowControl/BL']) sStr += `, flowControl/BL set` - if (status['flowControl/MRR']) sStr += `, flowControl/MRR set` - if (status['flowControl/MRC']) sStr += `, flowControl/MRC set` - if (status['forkID']) + if (isTruthy(status['serveHeaders'])) sStr += `, serveHeaders active` + if (isTruthy(status['serveChainSince'])) + sStr += `, ServeCS: ${buffer2int(status['serveChainSince'])}` + if (isTruthy(status['serveStateSince'])) + sStr += `, ServeSS: ${buffer2int(status['serveStateSince'])}` + if (isTruthy(status['txRelay'])) sStr += `, txRelay active` + if (isTruthy(status['flowControl/BL)'])) sStr += `, flowControl/BL set` + if (isTruthy(status['flowControl/MRR)'])) sStr += `, flowControl/MRR set` + if (isTruthy(status['flowControl/MRC)'])) sStr += `, flowControl/MRC set` + if (isTruthy(status['forkID'])) sStr += `, forkID: [crc32: ${status['forkID'][0].toString('hex')}, nextFork: ${buffer2int( status['forkID'][1] )}]` - if (status['recentTxLookup']) + if (isTruthy(status['recentTxLookup'])) sStr += `, recentTxLookup: ${buffer2int(status['recentTxLookup'])}` sStr += `]` return sStr @@ -151,7 +153,7 @@ export class LES extends Protocol { sendStatus(status: LES.Status) { if (this._status !== null) return - if (!status.announceType) { + if (isFalsy(status.announceType)) { status['announceType'] = int2buffer(DEFAULT_ANNOUNCE_TYPE) } status['protocolVersion'] = int2buffer(this._version) @@ -174,7 +176,11 @@ export class LES extends Protocol { let payload = Buffer.from(RLP.encode(bufArrToArr(statusList))) // Use snappy compression if peer supports DevP2P >=v5 - if (this._peer._hello?.protocolVersion && this._peer._hello?.protocolVersion >= 5) { + if ( + isTruthy(this._peer._hello) && + isTruthy(this._peer._hello.protocolVersion) && + this._peer._hello?.protocolVersion >= 5 + ) { payload = snappy.compress(payload) } @@ -237,7 +243,11 @@ export class LES extends Protocol { payload = Buffer.from(RLP.encode(payload)) // Use snappy compression if peer supports DevP2P >=v5 - if (this._peer._hello?.protocolVersion && this._peer._hello?.protocolVersion >= 5) { + if ( + isTruthy(this._peer._hello) && + isTruthy(this._peer._hello.protocolVersion) && + this._peer._hello?.protocolVersion >= 5 + ) { payload = snappy.compress(payload) } diff --git a/packages/devp2p/src/protocol/protocol.ts b/packages/devp2p/src/protocol/protocol.ts index a4219713e1..61a95b3a62 100644 --- a/packages/devp2p/src/protocol/protocol.ts +++ b/packages/devp2p/src/protocol/protocol.ts @@ -3,6 +3,7 @@ import { debug as createDebugLogger, Debugger } from 'debug' import { EventEmitter } from 'events' import { devp2pDebug } from '../util' import { Peer, DISCONNECT_REASONS } from '../rlpx/peer' +import { isTruthy } from '@ethereumjs/util' export enum EthProtocol { ETH = 'eth', @@ -63,7 +64,7 @@ export class Protocol extends EventEmitter { // Remote Peer IP logger const ip = this._peer._socket.remoteAddress - if (ip) { + if (isTruthy(ip)) { this.msgDebuggers[ip] = devp2pDebug.extend(ip) } } @@ -76,7 +77,7 @@ export class Protocol extends EventEmitter { */ _addFirstPeerDebugger() { const ip = this._peer._socket.remoteAddress - if (ip) { + if (isTruthy(ip)) { this.msgDebuggers[ip] = devp2pDebug.extend('FIRST_PEER') this._peer._addFirstPeerDebugger() this._firstPeer = ip @@ -91,11 +92,11 @@ export class Protocol extends EventEmitter { */ protected debug(messageName: string, msg: string) { this._debug(msg) - if (this.msgDebuggers[messageName]) { + if (isTruthy(this.msgDebuggers[messageName])) { this.msgDebuggers[messageName](msg) } const ip = this._peer._socket.remoteAddress - if (ip && this.msgDebuggers[ip]) { + if (isTruthy(ip) && isTruthy(this.msgDebuggers[ip])) { this.msgDebuggers[ip](msg) } } diff --git a/packages/devp2p/src/rlpx/ecies.ts b/packages/devp2p/src/rlpx/ecies.ts index 7695627a2c..bf17ee47ea 100644 --- a/packages/devp2p/src/rlpx/ecies.ts +++ b/packages/devp2p/src/rlpx/ecies.ts @@ -1,6 +1,6 @@ import * as crypto from 'crypto' import { debug as createDebugLogger } from 'debug' -import { bufArrToArr } from '@ethereumjs/util' +import { bufArrToArr, isFalsy, isTruthy } from '@ethereumjs/util' import { RLP } from 'rlp' import { getPublicKey } from 'ethereum-cryptography/secp256k1' import { unstrictDecode } from '../util' @@ -30,7 +30,7 @@ function ecdhX(publicKey: Buffer, privateKey: Buffer) { pubKey.set(x, 1) return pubKey.slice(1) } - return Buffer.from(ecdh(publicKey, privateKey, { hashfn: hashfn }, Buffer.alloc(32))) + return Buffer.from(ecdh(publicKey, privateKey, { hashfn }, Buffer.alloc(32))) } // a straigth rip from python interop w/go ecies implementation @@ -77,7 +77,7 @@ export class ECIES { constructor(privateKey: Buffer, id: Buffer, remoteId: Buffer) { this._privateKey = privateKey this._publicKey = id2pk(id) - this._remotePublicKey = remoteId ? id2pk(remoteId) : null + this._remotePublicKey = isTruthy(remoteId) ? id2pk(remoteId) : null this._nonce = crypto.randomBytes(32) this._ephemeralPrivateKey = genPrivateKey() @@ -166,7 +166,7 @@ export class ECIES { this._ingressMac.update(Buffer.concat([xor(macSecret, this._nonce), remoteData])) this._egressMac = new MAC(macSecret) - if (!this._initMsg) return + if (isFalsy(this._initMsg)) return this._egressMac.update(Buffer.concat([xor(macSecret, this._remoteNonce), this._initMsg])) } @@ -245,14 +245,16 @@ export class ECIES { const x = ecdhX(this._remotePublicKey, this._privateKey) - if (!this._remoteNonce) return + if (isFalsy(this._remoteNonce)) { + return + } this._remoteEphemeralPublicKey = Buffer.from( ecdsaRecover(signature, recoveryId, xor(x, this._remoteNonce), false) ) - if (!this._remoteEphemeralPublicKey) return + if (isFalsy(this._remoteEphemeralPublicKey)) return this._ephemeralSharedSecret = ecdhX(this._remoteEphemeralPublicKey, this._ephemeralPrivateKey) - if (heid !== null && this._remoteEphemeralPublicKey) { + if (heid !== null && isTruthy(this._remoteEphemeralPublicKey)) { assertEq( keccak256(pk2id(this._remoteEphemeralPublicKey)), heid, diff --git a/packages/devp2p/src/rlpx/peer.ts b/packages/devp2p/src/rlpx/peer.ts index 84431649e9..6a6bb75192 100644 --- a/packages/devp2p/src/rlpx/peer.ts +++ b/packages/devp2p/src/rlpx/peer.ts @@ -6,7 +6,7 @@ import * as snappy from 'snappyjs' import { debug as createDebugLogger, Debugger } from 'debug' import { devp2pDebug } from '../util' import { Common } from '@ethereumjs/common' -import { arrToBufArr, bufArrToArr } from '@ethereumjs/util' +import { arrToBufArr, bufArrToArr, isFalsy, isTruthy } from '@ethereumjs/util' import { RLP } from 'rlp' import { ETH, LES } from '../' import { int2buffer, buffer2int, formatLogData } from '../util' @@ -136,7 +136,7 @@ export class Peer extends EventEmitter { this._socket.on('data', this._onSocketData.bind(this)) this._socket.on('error', (err: Error) => this.emit('error', err)) this._socket.once('close', this._onSocketClose.bind(this)) - this._logger = this._socket.remoteAddress + this._logger = isTruthy(this._socket.remoteAddress) ? devp2pDebug.extend(this._socket.remoteAddress).extend(DEBUG_BASE_NAME) : devp2pDebug.extend(DEBUG_BASE_NAME) this._connected = false @@ -163,7 +163,7 @@ export class Peer extends EventEmitter { this._logger( `Send auth (EIP8: ${this._EIP8}) to ${this._socket.remoteAddress}:${this._socket.remotePort}` ) - if (this._EIP8) { + if (isTruthy(this._EIP8)) { const authEIP8 = this._eciesSession.createAuthEIP8() if (!authEIP8) return this._socket.write(authEIP8) @@ -240,7 +240,7 @@ export class Peer extends EventEmitter { this._sendMessage( PREFIXES.HELLO, Buffer.from(RLP.encode(bufArrToArr(payload as unknown as Buffer[]))) - ) + ) === true ) { this._weHello = payload } @@ -259,7 +259,7 @@ export class Peer extends EventEmitter { const debugMsg = `Send DISCONNECT to ${this._socket.remoteAddress}:${this._socket.remotePort} (reason: ${reasonName})` this.debug('DISCONNECT', debugMsg, reasonName) const data = Buffer.from(RLP.encode(reason)) - if (!this._sendMessage(PREFIXES.DISCONNECT, data)) return + if (this._sendMessage(PREFIXES.DISCONNECT, data) !== true) return this._disconnectReason = reason this._disconnectWe = true @@ -274,11 +274,15 @@ export class Peer extends EventEmitter { const debugMsg = `Send PING to ${this._socket.remoteAddress}:${this._socket.remotePort}` this.debug('PING', debugMsg) let data = Buffer.from(RLP.encode([])) - if (this._hello?.protocolVersion && this._hello.protocolVersion >= 5) { + if ( + isTruthy(this._hello) && + isTruthy(this._hello.protocolVersion) && + this._hello.protocolVersion >= 5 + ) { data = snappy.compress(data) } - if (!this._sendMessage(PREFIXES.PING, data)) return + if (this._sendMessage(PREFIXES.PING, data) !== true) return clearTimeout(this._pingTimeoutId!) this._pingTimeoutId = setTimeout(() => { @@ -294,7 +298,11 @@ export class Peer extends EventEmitter { this.debug('PONG', debugMsg) let data = Buffer.from(RLP.encode([])) - if (this._hello?.protocolVersion && this._hello.protocolVersion >= 5) { + if ( + isTruthy(this._hello) && + isTruthy(this._hello.protocolVersion) && + this._hello.protocolVersion >= 5 + ) { data = snappy.compress(data) } this._sendMessage(PREFIXES.PONG, data) @@ -372,7 +380,7 @@ export class Peer extends EventEmitter { return this.disconnect(DISCONNECT_REASONS.INVALID_IDENTITY) } - if (this._remoteClientIdFilter) { + if (isTruthy(this._remoteClientIdFilter)) { for (const filterStr of this._remoteClientIdFilter) { if (this._hello.clientId.toLowerCase().includes(filterStr.toLowerCase())) { return this.disconnect(DISCONNECT_REASONS.USELESS_PEER) @@ -384,7 +392,7 @@ export class Peer extends EventEmitter { for (const item of this._hello.capabilities) { for (const obj of this._capabilities!) { if (obj.name !== item.name || obj.version !== item.version) continue - if (shared[obj.name] && shared[obj.name].version > obj.version) continue + if (isTruthy(shared[obj.name]) && shared[obj.name].version > obj.version) continue shared[obj.name] = obj } } @@ -484,7 +492,7 @@ export class Peer extends EventEmitter { const parseData = this._socketData.slice(0, bytesCount) this._logger(`Received header ${this._socket.remoteAddress}:${this._socket.remotePort}`) const size = this._eciesSession.parseHeader(parseData) - if (!size) { + if (isFalsy(size)) { this._logger('invalid header size!') return } @@ -544,7 +552,11 @@ export class Peer extends EventEmitter { // Use snappy uncompression if peer supports DevP2P >=v5 let compressed = false const origPayload = payload - if (this._hello?.protocolVersion && this._hello?.protocolVersion >= 5) { + if ( + isTruthy(this._hello) && + isTruthy(this._hello.protocolVersion) && + this._hello?.protocolVersion >= 5 + ) { payload = snappy.uncompress(payload) compressed = true } @@ -673,7 +685,7 @@ export class Peer extends EventEmitter { */ _addFirstPeerDebugger() { const ip = this._socket.remoteAddress - if (ip) { + if (isTruthy(ip)) { this._logger = devp2pDebug.extend(ip).extend(`FIRST_PEER`).extend(DEBUG_BASE_NAME) } } @@ -686,7 +698,7 @@ export class Peer extends EventEmitter { * @param disconnectReason Capitalized disconnect reason (e.g. 'TIMEOUT') */ private debug(messageName: string, msg: string, disconnectReason?: string) { - if (disconnectReason) { + if (isTruthy(disconnectReason)) { this._logger.extend(messageName).extend(disconnectReason)(msg) } else { this._logger.extend(messageName)(msg) diff --git a/packages/devp2p/src/rlpx/rlpx.ts b/packages/devp2p/src/rlpx/rlpx.ts index b16d03c93c..ba015a2166 100644 --- a/packages/devp2p/src/rlpx/rlpx.ts +++ b/packages/devp2p/src/rlpx/rlpx.ts @@ -12,6 +12,7 @@ const { version: pVersion } = require('../../package.json') import { pk2id, createDeferred, formatLogId, buffer2int } from '../util' import { Peer, DISCONNECT_REASONS, Capabilities } from './peer' import { DPT, PeerInfo } from '../dpt' +import { isFalsy, isTruthy } from '@ethereumjs/util' const DEBUG_BASE_NAME = 'rlpx' const verbose = createDebugLogger('verbose').enabled @@ -73,7 +74,7 @@ export class RLPx extends EventEmitter { this._dpt = options.dpt ?? null if (this._dpt !== null) { this._dpt.on('peer:new', (peer: PeerInfo) => { - if (!peer.tcpPort) { + if (isFalsy(peer.tcpPort)) { this._dpt!.banPeer(peer, ms('5m')) this._debug(`banning peer with missing tcp port: ${peer.address}`) return @@ -101,8 +102,9 @@ export class RLPx extends EventEmitter { this._server.once('close', () => this.emit('close')) this._server.on('error', (err) => this.emit('error', err)) this._server.on('connection', (socket) => this._onConnect(socket, null)) - this._debug = this._server.address() - ? devp2pDebug.extend(DEBUG_BASE_NAME).extend(this._server.address() as string) + const serverAddress = this._server.address() + this._debug = isTruthy(serverAddress) + ? devp2pDebug.extend(DEBUG_BASE_NAME).extend(serverAddress as string) : devp2pDebug.extend(DEBUG_BASE_NAME) this._peers = new Map() this._peersQueue = [] @@ -132,7 +134,7 @@ export class RLPx extends EventEmitter { } async connect(peer: PeerInfo) { - if (!peer.tcpPort || !peer.address) return + if (isFalsy(peer.tcpPort) || isFalsy(peer.address)) return this._isAliveCheck() if (!Buffer.isBuffer(peer.id)) throw new TypeError('Expected peer.id as Buffer') @@ -187,7 +189,7 @@ export class RLPx extends EventEmitter { _connectToPeer(peer: PeerInfo) { this.connect(peer).catch((err) => { if (this._dpt === null) return - if (err.code === 'ECONNRESET' || err.toString().includes('Connection timeout')) { + if (err.code === 'ECONNRESET' || (err.toString() as string).includes('Connection timeout')) { this._dpt.banPeer(peer, ms('5m')) } }) @@ -242,14 +244,14 @@ export class RLPx extends EventEmitter { }) peer.once('close', (reason, disconnectWe) => { - if (disconnectWe) { + if (isTruthy(disconnectWe)) { this._debug( `disconnect from ${socket.remoteAddress}:${socket.remotePort}, reason: ${DISCONNECT_REASONS[reason]}`, `disconnect` ) } - if (!disconnectWe && reason === DISCONNECT_REASONS.TOO_MANY_PEERS) { + if (isFalsy(disconnectWe) && reason === DISCONNECT_REASONS.TOO_MANY_PEERS) { // hack if (this._getOpenQueueSlots() > 0) { this._peersQueue.push({ diff --git a/packages/devp2p/src/util.ts b/packages/devp2p/src/util.ts index 51a2712231..12aea3f52a 100644 --- a/packages/devp2p/src/util.ts +++ b/packages/devp2p/src/util.ts @@ -1,4 +1,4 @@ -import { arrToBufArr } from '@ethereumjs/util' +import { arrToBufArr, isTruthy } from '@ethereumjs/util' import { RLP } from 'rlp' import { utils } from 'ethereum-cryptography/secp256k1' import { publicKeyConvert } from 'ethereum-cryptography/secp256k1-compat' @@ -75,7 +75,7 @@ export function assertEq( if (expected.equals(actual)) return fullMsg = `${msg}: ${expected.toString('hex')} / ${actual.toString('hex')}` const debugMsg = `[ERROR] ${fullMsg}` - if (messageName) { + if (isTruthy(messageName)) { debug(messageName, debugMsg) } else { debug(debugMsg) @@ -85,7 +85,7 @@ export function assertEq( if (expected === actual) return fullMsg = `${msg}: ${expected} / ${actual}` - if (messageName) { + if (isTruthy(messageName)) { debug(messageName, fullMsg) } else { debug(fullMsg) diff --git a/packages/devp2p/test/integration/util.ts b/packages/devp2p/test/integration/util.ts index 5073411320..b84627b484 100644 --- a/packages/devp2p/test/integration/util.ts +++ b/packages/devp2p/test/integration/util.ts @@ -1,7 +1,8 @@ import * as test from 'tape' -import { DPT, ETH, RLPx, genPrivateKey } from '../../src' +import { Capabilities, DPT, ETH, RLPx, genPrivateKey } from '../../src' import { Chain, Common } from '@ethereumjs/common' import * as testdata from '../testdata.json' +import { isTruthy } from '@ethereumjs/util' type Test = test.Test @@ -66,11 +67,11 @@ export function destroyDPTs(dpts: DPT[]) { export function getTestRLPXs( numRLPXs: number, maxPeers: number = 10, - capabilities?: any, + capabilities?: Capabilities[], common?: Object | Common ) { const rlpxs = [] - if (!capabilities) { + if (typeof capabilities === 'undefined') { capabilities = [ETH.eth66, ETH.eth65, ETH.eth64, ETH.eth63, ETH.eth62] } if (!common) { @@ -123,13 +124,13 @@ export function twoPeerMsgExchange( protocol.sendStatus(opts.status0) // (1 ->) protocol.once('status', () => { - if (opts.onOnceStatus0) opts.onOnceStatus0(rlpxs, protocol) + if (isTruthy(opts.onOnceStatus0)) opts.onOnceStatus0(rlpxs, protocol) }) // (-> 2) protocol.on('message', async (code: any, payload: any) => { - if (opts.onOnMsg0) opts.onOnMsg0(rlpxs, protocol, code, payload) + if (isTruthy(opts.onOnMsg0)) opts.onOnMsg0(rlpxs, protocol, code, payload) }) peer.on('error', (err: Error) => { - if (opts.onPeerError0) { + if (isTruthy(opts.onPeerError0)) { opts.onPeerError0(err, rlpxs) } else { t.fail(`Unexpected peer 0 error: ${err}`) @@ -148,10 +149,10 @@ export function twoPeerMsgExchange( protocol.sendStatus(opts.status1) // (2 ->) break } - if (opts.onOnMsg1) opts.onOnMsg1(rlpxs, protocol, code, payload) + if (isTruthy(opts.onOnMsg1)) opts.onOnMsg1(rlpxs, protocol, code, payload) }) peer.on('error', (err: any) => { - if (opts.onPeerError1) { + if (isTruthy(opts.onPeerError1)) { opts.onPeerError1(err, rlpxs) } else { t.fail(`Unexpected peer 1 error: ${err}`) diff --git a/packages/devp2p/test/rlpx-ecies.ts b/packages/devp2p/test/rlpx-ecies.ts index 890cb203d0..456a345638 100644 --- a/packages/devp2p/test/rlpx-ecies.ts +++ b/packages/devp2p/test/rlpx-ecies.ts @@ -10,7 +10,12 @@ type Test = test.Test declare module 'tape' { export interface Test { - context: any + context: { + a: ECIES + b: ECIES + h0?: { auth: Buffer; ack: Buffer } + h1?: { auth: Buffer; ack: Buffer } + } } } @@ -59,7 +64,7 @@ test( randomBefore((t: Test) => { const message = Buffer.from('The Magic Words are Squeamish Ossifrage') const encrypted = t.context.a._encryptMessage(message) - const decrypted = t.context.b._decryptMessage(encrypted) + const decrypted = t.context.b._decryptMessage(encrypted as Buffer) t.same(message, decrypted, 'encryptMessage -> decryptMessage should lead to same') t.end() }) @@ -71,20 +76,21 @@ test( t.doesNotThrow(() => { const auth = t.context.a.createAuthNonEIP8() t.context.b._gotEIP8Auth = false - t.context.b.parseAuthPlain(auth) + t.context.b.parseAuthPlain(auth as Buffer) }, 'should not throw on auth creation/parsing') t.doesNotThrow(() => { t.context.b._gotEIP8Ack = false const ack = t.context.b.createAckOld() - t.context.a.parseAckPlain(ack) + t.context.a.parseAckPlain(ack as Buffer) }, 'should not throw on ack creation/parsing') const body = randomBytes(600) - const header = t.context.b.parseHeader(t.context.a.createHeader(body.length)) + + const header = t.context.b.parseHeader(t.context.a.createHeader(body.length) as Buffer) t.same(header, body.length, 'createHeader -> parseHeader should lead to same') - const parsedBody = t.context.b.parseBody(t.context.a.createBody(body)) + const parsedBody = t.context.b.parseBody(t.context.a.createBody(body) as Buffer) t.same(parsedBody, body, 'createBody -> parseBody should lead to same') t.end() @@ -97,13 +103,13 @@ test( t.doesNotThrow(() => { const auth = t.context.a.createAuthEIP8() t.context.b._gotEIP8Auth = true - t.context.b.parseAuthEIP8(auth) + t.context.b.parseAuthEIP8(auth as Buffer) }, 'should not throw on auth creation/parsing') t.doesNotThrow(() => { const ack = t.context.b.createAckEIP8() t.context.a._gotEIP8Ack = true - t.context.a.parseAckEIP8(ack) + t.context.a.parseAckEIP8(ack as Buffer) }, 'should not throw on ack creation/parsing') t.end() @@ -115,13 +121,13 @@ test( testdataBefore((t: Test) => { t.doesNotThrow(() => { t.context.b._gotEIP8Auth = false - t.context.b.parseAuthPlain(t.context.h0.auth) - t.context.a._initMsg = t.context.h0.auth + t.context.b.parseAuthPlain(t.context.h0?.auth as Buffer) + t.context.a._initMsg = t.context.h0?.auth }, 'should not throw on auth parsing') t.doesNotThrow(() => { t.context.a._gotEIP8Ack = false - t.context.a.parseAckPlain(t.context.h0.ack) + t.context.a.parseAckPlain(t.context.h0?.ack as Buffer) }, 'should not throw on ack parsing') t.end() @@ -133,12 +139,12 @@ test( testdataBefore((t: Test) => { t.doesNotThrow(() => { t.context.b._gotEIP8Auth = true - t.context.b.parseAuthEIP8(t.context.h1.auth) - t.context.a._initMsg = t.context.h1.auth + t.context.b.parseAuthEIP8(t.context.h1?.auth as Buffer) + t.context.a._initMsg = t.context.h1?.auth }, 'should not throw on auth parsing') t.doesNotThrow(() => { t.context.a._gotEIP8Ack = true - t.context.a.parseAckEIP8(t.context.h1.ack) + t.context.a.parseAckEIP8(t.context.h1?.ack as Buffer) }, 'should not throw on ack parsing') t.end() diff --git a/packages/ethash/src/index.ts b/packages/ethash/src/index.ts index 069da3fa97..198bfe485c 100644 --- a/packages/ethash/src/index.ts +++ b/packages/ethash/src/index.ts @@ -6,6 +6,8 @@ import { bufArrToArr, bufferToBigInt, setLengthLeft, + isTruthy, + isFalsy, } from '@ethereumjs/util' import { RLP } from 'rlp' import { @@ -133,7 +135,7 @@ export class Miner { }, 0) }) - if (solution) { + if (isTruthy(solution)) { return solution } } @@ -203,10 +205,10 @@ export class Ethash { } run(val: Buffer, nonce: Buffer, fullSize?: number) { - if (!fullSize && this.fullSize) { + if (isFalsy(fullSize) && isTruthy(this.fullSize)) { fullSize = this.fullSize } - if (!fullSize) { + if (isFalsy(fullSize)) { throw new Error('fullSize needed') } const n = Math.floor(fullSize / params.HASH_BYTES) diff --git a/packages/evm/src/evm.ts b/packages/evm/src/evm.ts index a1622556ac..f5c8978ed9 100644 --- a/packages/evm/src/evm.ts +++ b/packages/evm/src/evm.ts @@ -8,6 +8,8 @@ import { bigIntToBuffer, generateAddress, generateAddress2, + isFalsy, + isTruthy, KECCAK256_NULL, MAX_INTEGER, short, @@ -43,7 +45,7 @@ const isBrowser = new Function('try {return this===window;}catch(e){ return fals let mcl: any let mclInitPromise: any -if (!isBrowser()) { +if (isBrowser() === false) { mcl = require('mcl-wasm') mclInitPromise = mcl.init(mcl.BLS12_381) } @@ -280,7 +282,7 @@ export class EVM extends AsyncEventEmitter implements EVMInterface { this._precompiles = getActivePrecompiles(this._common, this._customPrecompiles) if (this._common.isActivatedEIP(2537)) { - if (isBrowser()) { + if (isBrowser() === true) { throw new Error('EIP-2537 is currently not supported in browsers') } else { this._mcl = mcl @@ -288,7 +290,7 @@ export class EVM extends AsyncEventEmitter implements EVMInterface { } // Safeguard if "process" is not available (browser) - if (process !== undefined && process.env.DEBUG) { + if (typeof process?.env.DEBUG !== 'undefined') { this.DEBUG = true } @@ -303,7 +305,7 @@ export class EVM extends AsyncEventEmitter implements EVMInterface { } if (this._common.isActivatedEIP(2537)) { - if (isBrowser()) { + if (isBrowser() === true) { throw new Error('EIP-2537 is currently not supported in browsers') } else { const mcl = this._mcl @@ -360,7 +362,7 @@ export class EVM extends AsyncEventEmitter implements EVMInterface { debug(`Exit early on no code`) } } - if (errorMessage) { + if (isTruthy(errorMessage)) { exit = true if (this.DEBUG) { debug(`Exit early on value transfer overflowed`) @@ -472,13 +474,13 @@ export class EVM extends AsyncEventEmitter implements EVMInterface { } let exit = false - if (!message.code || message.code.length === 0) { + if (isFalsy(message.code) || message.code.length === 0) { exit = true if (this.DEBUG) { debug(`Exit early on no code`) } } - if (errorMessage) { + if (isTruthy(errorMessage)) { exit = true if (this.DEBUG) { debug(`Exit early on value transfer overflowed`) @@ -533,7 +535,7 @@ export class EVM extends AsyncEventEmitter implements EVMInterface { // Begin EOF1 contract code checks // EIP-3540 EOF1 header check const eof1CodeAnalysisResults = EOF.codeAnalysis(result.returnValue) - if (!eof1CodeAnalysisResults?.code) { + if (typeof eof1CodeAnalysisResults?.code === 'undefined') { result = { ...result, ...INVALID_EOF_RESULT(message.gasLimit), @@ -582,7 +584,11 @@ export class EVM extends AsyncEventEmitter implements EVMInterface { } // Save code if a new contract was created - if (!result.exceptionError && result.returnValue && result.returnValue.toString() !== '') { + if ( + !result.exceptionError && + isTruthy(result.returnValue) && + result.returnValue.toString() !== '' + ) { await this.eei.putContractCode(message.to, result.returnValue) if (this.DEBUG) { debug(`Code saved on new contract creation`) @@ -686,7 +692,7 @@ export class EVM extends AsyncEventEmitter implements EVMInterface { const caller = opts.caller ?? Address.zero() const value = opts.value ?? BigInt(0) - if (opts.skipBalance) { + if (opts.skipBalance === true) { // if skipBalance, add `value` to caller balance to ensure sufficient funds const callerAccount = await this.eei.getAccount(caller) callerAccount.balance += value @@ -711,7 +717,7 @@ export class EVM extends AsyncEventEmitter implements EVMInterface { await this._emit('beforeMessage', message) - if (!message.to && this._common.isActivatedEIP(2929)) { + if (!message.to && this._common.isActivatedEIP(2929) === true) { message.code = message.data this.eei.addWarmedAddress((await this._generateAddress(message)).buf) } diff --git a/packages/evm/src/interpreter.ts b/packages/evm/src/interpreter.ts index c645135573..69104e5dd8 100644 --- a/packages/evm/src/interpreter.ts +++ b/packages/evm/src/interpreter.ts @@ -5,6 +5,8 @@ import { bigIntToHex, bufferToBigInt, intToHex, + isFalsy, + isTruthy, MAX_UINT64, } from '@ethereumjs/util' @@ -398,7 +400,11 @@ export class Interpreter { useGas(amount: bigint, context?: string): void { this._runState.gasLeft -= amount if (this._evm.DEBUG) { - debugGas(`${context ? context + ': ' : ''}used ${amount} gas (-> ${this._runState.gasLeft})`) + debugGas( + `${typeof context === 'string' ? context + ': ' : ''}used ${amount} gas (-> ${ + this._runState.gasLeft + })` + ) } if (this._runState.gasLeft < BigInt(0)) { this._runState.gasLeft = BigInt(0) @@ -414,7 +420,9 @@ export class Interpreter { refundGas(amount: bigint, context?: string): void { if (this._evm.DEBUG) { debugGas( - `${context ? context + ': ' : ''}refund ${amount} gas (-> ${this._runState.gasRefund})` + `${typeof context === 'string' ? context + ': ' : ''}refund ${amount} gas (-> ${ + this._runState.gasRefund + })` ) } this._runState.gasRefund += amount @@ -428,7 +436,9 @@ export class Interpreter { subRefund(amount: bigint, context?: string): void { if (this._evm.DEBUG) { debugGas( - `${context ? context + ': ' : ''}sub gas refund ${amount} (-> ${this._runState.gasRefund})` + `${typeof context === 'string' ? context + ': ' : ''}sub gas refund ${amount} (-> ${ + this._runState.gasRefund + })` ) } this._runState.gasRefund -= amount @@ -823,7 +833,7 @@ export class Interpreter { // Set return value if ( - results.execResult.returnValue && + isTruthy(results.execResult.returnValue) && (!results.execResult.exceptionError || results.execResult.exceptionError.error === ERROR.REVERT) ) { @@ -940,7 +950,7 @@ export class Interpreter { async _selfDestruct(toAddress: Address): Promise { // only add to refund if this is the first selfdestruct for the address - if (!this._result.selfdestruct[this._env.address.buf.toString('hex')]) { + if (isFalsy(this._result.selfdestruct[this._env.address.buf.toString('hex')])) { this.refundGas(this._common.param('gasPrices', 'selfdestructRefund')) } diff --git a/packages/evm/src/opcodes/EIP2929.ts b/packages/evm/src/opcodes/EIP2929.ts index e5cd08a481..a2da737aee 100644 --- a/packages/evm/src/opcodes/EIP2929.ts +++ b/packages/evm/src/opcodes/EIP2929.ts @@ -19,7 +19,7 @@ export function accessAddressEIP2929( chargeGas = true, isSelfdestructOrAuthcall = false ): bigint { - if (!common.isActivatedEIP(2929)) return BigInt(0) + if (common.isActivatedEIP(2929) === false) return BigInt(0) const eei = runState.eei const addressStr = address.buf @@ -54,7 +54,7 @@ export function accessStorageEIP2929( isSstore: boolean, common: Common ): bigint { - if (!common.isActivatedEIP(2929)) return BigInt(0) + if (common.isActivatedEIP(2929) === false) return BigInt(0) const eei = runState.eei const address = runState.interpreter.getAddress().buf @@ -87,7 +87,7 @@ export function adjustSstoreGasEIP2929( costName: string, common: Common ): bigint { - if (!common.isActivatedEIP(2929)) return defaultCost + if (common.isActivatedEIP(2929) === false) return defaultCost const eei = runState.eei const address = runState.interpreter.getAddress().buf diff --git a/packages/evm/src/opcodes/codes.ts b/packages/evm/src/opcodes/codes.ts index c2e125c9d7..c5d552f77f 100644 --- a/packages/evm/src/opcodes/codes.ts +++ b/packages/evm/src/opcodes/codes.ts @@ -3,6 +3,7 @@ import { CustomOpcode } from '../types' import { getFullname } from './util' import { AsyncDynamicGasHandler, dynamicGasHandlers, SyncDynamicGasHandler } from './gas' import { handlers, OpHandler } from './functions' +import { isTruthy } from '@ethereumjs/util' export class Opcode { readonly code: number @@ -373,7 +374,7 @@ export function getOpcodesForHF(common: Common, customOpcodes?: CustomOpcode[]): }, } opcodeBuilder = { ...opcodeBuilder, ...entry } - if (code.gasFunction) { + if (isTruthy(code.gasFunction)) { dynamicGasHandlersCopy.set(code.opcode, code.gasFunction) } // logicFunction is never undefined diff --git a/packages/evm/src/opcodes/gas.ts b/packages/evm/src/opcodes/gas.ts index 52cb44a9a4..7b7f700f35 100644 --- a/packages/evm/src/opcodes/gas.ts +++ b/packages/evm/src/opcodes/gas.ts @@ -68,7 +68,7 @@ export const dynamicGasHandlers: Map { - if (common.isActivatedEIP(2929)) { + if (common.isActivatedEIP(2929) === true) { const addressBigInt = runState.stack.peek()[0] const address = new Address(addressToBuffer(addressBigInt)) gas += accessAddressEIP2929(runState, address, common) @@ -106,7 +106,7 @@ export const dynamicGasHandlers: Map { - if (common.isActivatedEIP(2929)) { + if (common.isActivatedEIP(2929) === true) { const addressBigInt = runState.stack.peek()[0] const address = new Address(addressToBuffer(addressBigInt)) gas += accessAddressEIP2929(runState, address, common) @@ -122,7 +122,7 @@ export const dynamicGasHandlers: Map { - if (common.isActivatedEIP(2929)) { + if (common.isActivatedEIP(2929) === true) { const addressBigInt = runState.stack.peek()[0] const address = new Address(addressToBuffer(addressBigInt)) gas += accessAddressEIP2929(runState, address, common) @@ -197,7 +197,7 @@ export const dynamicGasHandlers: Map { - if (!opts.data) throw new Error('opts.data missing but required') + if (isFalsy(opts.data)) throw new Error('opts.data missing but required') const mcl = (opts._EVM)._mcl! diff --git a/packages/evm/src/precompiles/0b-bls12-g1mul.ts b/packages/evm/src/precompiles/0b-bls12-g1mul.ts index af1000b345..3a894b4eb9 100644 --- a/packages/evm/src/precompiles/0b-bls12-g1mul.ts +++ b/packages/evm/src/precompiles/0b-bls12-g1mul.ts @@ -1,6 +1,7 @@ import { PrecompileInput } from './types' import { EvmErrorResult, ExecResult, OOGResult } from '../evm' import { ERROR, EvmError } from '../exceptions' +import { isFalsy } from '@ethereumjs/util' const { BLS12_381_ToG1Point, BLS12_381_FromG1Point, @@ -8,7 +9,7 @@ const { } = require('./util/bls12_381') export async function precompile0b(opts: PrecompileInput): Promise { - if (!opts.data) throw new Error('opts.data missing but required') + if (isFalsy(opts.data)) throw new Error('opts.data missing but required') const mcl = (opts._EVM)._mcl! diff --git a/packages/evm/src/precompiles/0c-bls12-g1multiexp.ts b/packages/evm/src/precompiles/0c-bls12-g1multiexp.ts index 9732fd0e1e..95e048ee54 100644 --- a/packages/evm/src/precompiles/0c-bls12-g1multiexp.ts +++ b/packages/evm/src/precompiles/0c-bls12-g1multiexp.ts @@ -1,6 +1,7 @@ import { PrecompileInput } from './types' import { EvmErrorResult, ExecResult, OOGResult } from '../evm' import { ERROR, EvmError } from '../exceptions' +import { isFalsy } from '@ethereumjs/util' const { BLS12_381_ToG1Point, BLS12_381_ToFrPoint, @@ -8,7 +9,7 @@ const { } = require('./util/bls12_381') export async function precompile0c(opts: PrecompileInput): Promise { - if (!opts.data) throw new Error('opts.data missing but required') + if (isFalsy(opts.data)) throw new Error('opts.data missing but required') const mcl = (opts._EVM)._mcl! diff --git a/packages/evm/src/precompiles/0d-bls12-g2add.ts b/packages/evm/src/precompiles/0d-bls12-g2add.ts index 3567f9c471..7709a26ee6 100644 --- a/packages/evm/src/precompiles/0d-bls12-g2add.ts +++ b/packages/evm/src/precompiles/0d-bls12-g2add.ts @@ -1,10 +1,11 @@ import { PrecompileInput } from './types' import { EvmErrorResult, ExecResult, OOGResult } from '../evm' import { ERROR, EvmError } from '../exceptions' +import { isFalsy } from '@ethereumjs/util' const { BLS12_381_ToG2Point, BLS12_381_FromG2Point } = require('./util/bls12_381') export async function precompile0d(opts: PrecompileInput): Promise { - if (!opts.data) throw new Error('opts.data missing but required') + if (isFalsy(opts.data)) throw new Error('opts.data missing but required') const mcl = (opts._EVM)._mcl! diff --git a/packages/evm/src/precompiles/0e-bls12-g2mul.ts b/packages/evm/src/precompiles/0e-bls12-g2mul.ts index e5933152a0..cfee1240ed 100644 --- a/packages/evm/src/precompiles/0e-bls12-g2mul.ts +++ b/packages/evm/src/precompiles/0e-bls12-g2mul.ts @@ -1,6 +1,7 @@ import { PrecompileInput } from './types' import { EvmErrorResult, ExecResult, OOGResult } from '../evm' import { ERROR, EvmError } from '../exceptions' +import { isFalsy } from '@ethereumjs/util' const { BLS12_381_ToG2Point, BLS12_381_FromG2Point, @@ -8,7 +9,7 @@ const { } = require('./util/bls12_381') export async function precompile0e(opts: PrecompileInput): Promise { - if (!opts.data) throw new Error('opts.data missing but required') + if (isFalsy(opts.data)) throw new Error('opts.data missing but required') const mcl = (opts._EVM)._mcl! diff --git a/packages/evm/src/precompiles/0f-bls12-g2multiexp.ts b/packages/evm/src/precompiles/0f-bls12-g2multiexp.ts index d1c77dc0c2..fe0eb6dc59 100644 --- a/packages/evm/src/precompiles/0f-bls12-g2multiexp.ts +++ b/packages/evm/src/precompiles/0f-bls12-g2multiexp.ts @@ -2,6 +2,7 @@ import { PrecompileInput } from './types' import { EvmErrorResult, ExecResult, OOGResult } from '../evm' import { ERROR, EvmError } from '../exceptions' import { gasDiscountPairs } from './util/bls12_381' +import { isFalsy } from '@ethereumjs/util' const { BLS12_381_ToG2Point, BLS12_381_ToFrPoint, @@ -9,7 +10,7 @@ const { } = require('./util/bls12_381') export async function precompile0f(opts: PrecompileInput): Promise { - if (!opts.data) throw new Error('opts.data missing but required') + if (isFalsy(opts.data)) throw new Error('opts.data missing but required') const mcl = (opts._EVM)._mcl! diff --git a/packages/evm/src/precompiles/10-bls12-pairing.ts b/packages/evm/src/precompiles/10-bls12-pairing.ts index 72b507e989..f98aa23a4a 100644 --- a/packages/evm/src/precompiles/10-bls12-pairing.ts +++ b/packages/evm/src/precompiles/10-bls12-pairing.ts @@ -1,6 +1,7 @@ import { PrecompileInput } from './types' import { EvmErrorResult, ExecResult, OOGResult } from '../evm' import { ERROR, EvmError } from '../exceptions' +import { isFalsy } from '@ethereumjs/util' const { BLS12_381_ToG1Point, BLS12_381_ToG2Point } = require('./util/bls12_381') @@ -8,7 +9,7 @@ const zeroBuffer = Buffer.alloc(32, 0) const oneBuffer = Buffer.concat([Buffer.alloc(31, 0), Buffer.from('01', 'hex')]) export async function precompile10(opts: PrecompileInput): Promise { - if (!opts.data) throw new Error('opts.data missing but required') + if (isFalsy(opts.data)) throw new Error('opts.data missing but required') const mcl = (opts._EVM)._mcl! @@ -98,7 +99,7 @@ export async function precompile10(opts: PrecompileInput): Promise { let returnValue - if (GT.isOne()) { + if (GT.isOne() === true) { returnValue = oneBuffer } else { returnValue = zeroBuffer diff --git a/packages/evm/src/precompiles/11-bls12-map-fp-to-g1.ts b/packages/evm/src/precompiles/11-bls12-map-fp-to-g1.ts index 53059d41f4..306ace3826 100644 --- a/packages/evm/src/precompiles/11-bls12-map-fp-to-g1.ts +++ b/packages/evm/src/precompiles/11-bls12-map-fp-to-g1.ts @@ -1,10 +1,11 @@ import { PrecompileInput } from './types' import { EvmErrorResult, ExecResult, OOGResult } from '../evm' import { ERROR, EvmError } from '../exceptions' +import { isFalsy } from '@ethereumjs/util' const { BLS12_381_ToFpPoint, BLS12_381_FromG1Point } = require('./util/bls12_381') export async function precompile11(opts: PrecompileInput): Promise { - if (!opts.data) throw new Error('opts.data missing but required') + if (isFalsy(opts.data)) throw new Error('opts.data missing but required') const mcl = (opts._EVM)._mcl! diff --git a/packages/evm/src/precompiles/12-bls12-map-fp2-to-g2.ts b/packages/evm/src/precompiles/12-bls12-map-fp2-to-g2.ts index ed56d9fb67..d13bbc46a5 100644 --- a/packages/evm/src/precompiles/12-bls12-map-fp2-to-g2.ts +++ b/packages/evm/src/precompiles/12-bls12-map-fp2-to-g2.ts @@ -1,10 +1,11 @@ import { PrecompileInput } from './types' import { EvmErrorResult, ExecResult, OOGResult } from '../evm' import { ERROR, EvmError } from '../exceptions' +import { isFalsy } from '@ethereumjs/util' const { BLS12_381_ToFp2Point, BLS12_381_FromG2Point } = require('./util/bls12_381') export async function precompile12(opts: PrecompileInput): Promise { - if (!opts.data) throw new Error('opts.data missing but required') + if (isFalsy(opts.data)) throw new Error('opts.data missing but required') const mcl = (opts._EVM)._mcl! diff --git a/packages/evm/src/precompiles/index.ts b/packages/evm/src/precompiles/index.ts index abff4d8b04..4aafece321 100644 --- a/packages/evm/src/precompiles/index.ts +++ b/packages/evm/src/precompiles/index.ts @@ -1,4 +1,4 @@ -import { Address } from '@ethereumjs/util' +import { Address, isTruthy } from '@ethereumjs/util' import { Common, Hardfork } from '@ethereumjs/common' import { PrecompileInput, PrecompileFunc } from './types' import { precompile01 } from './01-ecrecover' @@ -146,7 +146,7 @@ const precompileAvailability: PrecompileAvailability = { function getPrecompile(address: Address, common: Common): PrecompileFunc { const addr = address.buf.toString('hex') - if (precompiles[addr]) { + if (isTruthy(precompiles[addr])) { const availability = precompileAvailability[addr] if ( (availability.type == PrecompileAvailabilityCheck.Hardfork && @@ -190,7 +190,7 @@ function getActivePrecompiles( } const address = new Address(Buffer.from(addressString, 'hex')) const precompileFunc = getPrecompile(address, common) - if (precompileFunc) { + if (isTruthy(precompileFunc)) { precompileMap.set(addressString, precompileFunc) } } diff --git a/packages/evm/src/precompiles/util/bls12_381.ts b/packages/evm/src/precompiles/util/bls12_381.ts index 67f7c1ab85..29377b7cf8 100644 --- a/packages/evm/src/precompiles/util/bls12_381.ts +++ b/packages/evm/src/precompiles/util/bls12_381.ts @@ -163,12 +163,12 @@ function BLS12_381_ToG1Point(input: Buffer, mcl: any): any { G1.setY(Fp_Y) G1.setZ(One) - if (!G1.isValidOrder()) { + if (G1.isValidOrder() === false) { throw new EvmError(ERROR.BLS_12_381_POINT_NOT_ON_CURVE) } // Check if these coordinates are actually on the curve. - if (!G1.isValid()) { + if (G1.isValid() === false) { throw new EvmError(ERROR.BLS_12_381_POINT_NOT_ON_CURVE) } @@ -237,11 +237,11 @@ function BLS12_381_ToG2Point(input: Buffer, mcl: any): any { mclPoint.setY(Fp2Y) mclPoint.setZ(Fp2One) - if (!mclPoint.isValidOrder()) { + if (mclPoint.isValidOrder() === false) { throw new EvmError(ERROR.BLS_12_381_POINT_NOT_ON_CURVE) } - if (!mclPoint.isValid()) { + if (mclPoint.isValid() === false) { throw new EvmError(ERROR.BLS_12_381_POINT_NOT_ON_CURVE) } diff --git a/packages/evm/tests/precompiles/hardfork.spec.ts b/packages/evm/tests/precompiles/hardfork.spec.ts index 897ba2d5c8..d229267dea 100644 --- a/packages/evm/tests/precompiles/hardfork.spec.ts +++ b/packages/evm/tests/precompiles/hardfork.spec.ts @@ -1,5 +1,5 @@ import * as tape from 'tape' -import { Address } from '@ethereumjs/util' +import { Address, isFalsy } from '@ethereumjs/util' import { Chain, Common, Hardfork } from '@ethereumjs/common' import { EVM } from '../../src' import { getActivePrecompiles } from '../../src/precompiles' @@ -35,7 +35,7 @@ tape('Precompiles: hardfork availability', (t) => { // Check if ECPAIR is available in future hard forks. const commonPetersburg = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Petersburg }) ECPAIRING = getActivePrecompiles(commonPetersburg).get(ECPAIR_AddressStr)! - if (!ECPAIRING) { + if (isFalsy(ECPAIRING)) { st.fail('ECPAIRING is not available in petersburg while it should be available') } else { st.pass('ECPAIRING available in petersburg') diff --git a/packages/evm/tests/runCode.spec.ts b/packages/evm/tests/runCode.spec.ts index 9574fee2bf..32a369f4ed 100644 --- a/packages/evm/tests/runCode.spec.ts +++ b/packages/evm/tests/runCode.spec.ts @@ -1,6 +1,7 @@ import * as tape from 'tape' import { getEEI } from './utils' import { EVM } from '../src' +import { isFalsy, isTruthy } from '@ethereumjs/util' const STOP = '00' const JUMP = '56' @@ -43,13 +44,13 @@ tape('VM.runCode: initial program counter', async (t) => { err = e } - if (testData.error) { - err = err ? err.message : 'no error thrown' + if (isTruthy(testData.error)) { + err = isTruthy(err) ? err.message : 'no error thrown' t.equal(err, testData.error, 'error message should match') err = false } - t.assert(!err) + t.assert(isFalsy(err)) } }) diff --git a/packages/evm/tests/utils.ts b/packages/evm/tests/utils.ts index 0f9be7993f..4e3cead359 100644 --- a/packages/evm/tests/utils.ts +++ b/packages/evm/tests/utils.ts @@ -1,7 +1,7 @@ import { Blockchain } from '../../blockchain/src' import { Chain, Common } from '@ethereumjs/common' import { DefaultStateManager } from '@ethereumjs/statemanager' -import { Account } from '@ethereumjs/util' +import { Account, isTruthy } from '@ethereumjs/util' import path from 'path' import { EEI } from '../../vm/src/eei/eei' @@ -21,9 +21,9 @@ export function createAccount(nonce = BigInt(0), balance = BigInt(0xfff384)) { * Checks if in a karma test runner. * @returns boolean whether running in karma */ -export function isRunningInKarma(): Boolean { +export function isRunningInKarma(): boolean { // eslint-disable-next-line no-undef - return typeof (globalThis).window !== 'undefined' && (globalThis).window.__karma__ + return isTruthy((globalThis).window?.__karma__) } /** diff --git a/packages/rlp/src/index.ts b/packages/rlp/src/index.ts index b3b2136638..35e4030327 100644 --- a/packages/rlp/src/index.ts +++ b/packages/rlp/src/index.ts @@ -74,7 +74,7 @@ function encodeLength(len: number, offset: number): Uint8Array { export function decode(input: Input, stream?: false): Uint8Array | NestedUint8Array export function decode(input: Input, stream?: true): Decoded export function decode(input: Input, stream = false): Uint8Array | NestedUint8Array | Decoded { - if (!input || (input as any).length === 0) { + if (typeof input === 'undefined' || input === null || (input as any).length === 0) { return Uint8Array.from([]) } diff --git a/packages/rlp/test/dataTypes.spec.ts b/packages/rlp/test/dataTypes.spec.ts index 175e5b1464..b58de6f304 100644 --- a/packages/rlp/test/dataTypes.spec.ts +++ b/packages/rlp/test/dataTypes.spec.ts @@ -27,7 +27,7 @@ tape('invalid RLPs', (t) => { RLP.decode(input) st.ok(false) } catch (e: any) { - if (msg) { + if (typeof msg !== 'undefined') { st.deepEqual(e.message, msg) } else { // FIXME: check for exception name diff --git a/packages/statemanager/src/baseStateManager.ts b/packages/statemanager/src/baseStateManager.ts index 2dc8c2b6b6..0126d50ff8 100644 --- a/packages/statemanager/src/baseStateManager.ts +++ b/packages/statemanager/src/baseStateManager.ts @@ -43,7 +43,7 @@ export abstract class BaseStateManager { this._common = common // Safeguard if "process" is not available (browser) - if (process !== undefined && process.env.DEBUG) { + if (typeof process?.env.DEBUG !== 'undefined') { this.DEBUG = true } this._debug = createDebugLogger('statemanager:statemanager') diff --git a/packages/statemanager/src/cache.ts b/packages/statemanager/src/cache.ts index 9d6e325a01..32f8c3449e 100644 --- a/packages/statemanager/src/cache.ts +++ b/packages/statemanager/src/cache.ts @@ -1,4 +1,4 @@ -import { Account, Address } from '@ethereumjs/util' +import { Account, Address, isFalsy, isTruthy } from '@ethereumjs/util' const Tree = require('functional-red-black-tree') export type getCb = (address: Address) => Promise @@ -57,7 +57,7 @@ export class Cache { const keyStr = key.buf.toString('hex') const it = this._cache.find(keyStr) - if (it.node) { + if (isTruthy(it.node)) { const rlp = it.value.val const account = Account.fromRlpSerializedAccount(rlp) ;(account as any).virtual = it.value.virtual @@ -72,7 +72,7 @@ export class Cache { keyIsDeleted(key: Address): boolean { const keyStr = key.buf.toString('hex') const it = this._cache.find(keyStr) - if (it.node) { + if (isTruthy(it.node)) { return it.value.deleted } return false @@ -108,14 +108,14 @@ export class Cache { const it = this._cache.begin let next = true while (next) { - if (it.value && it.value.modified && !it.value.deleted) { + if (isTruthy(it.value) && isTruthy(it.value.modified) && isFalsy(it.value.deleted)) { it.value.modified = false const accountRlp = it.value.val const keyBuf = Buffer.from(it.key, 'hex') await this._putCb(keyBuf, accountRlp) next = it.hasNext it.next() - } else if (it.value && it.value.modified && it.value.deleted) { + } else if (isTruthy(it.value) && isTruthy(it.value.modified) && isTruthy(it.value.deleted)) { it.value.modified = false it.value.deleted = true it.value.virtual = true @@ -187,7 +187,7 @@ export class Cache { const keyHex = key.buf.toString('hex') const it = this._cache.find(keyHex) const val = value.serialize() - if (it.node) { + if (isTruthy(it.node)) { this._cache = it.update({ val, modified, deleted, virtual }) } else { this._cache = this._cache.insert(keyHex, { val, modified, deleted, virtual }) diff --git a/packages/statemanager/src/stateManager.ts b/packages/statemanager/src/stateManager.ts index 2904d239f9..0e63991e5e 100644 --- a/packages/statemanager/src/stateManager.ts +++ b/packages/statemanager/src/stateManager.ts @@ -12,6 +12,8 @@ import { KECCAK256_RLP, setLengthLeft, short, + isFalsy, + isTruthy, } from '@ethereumjs/util' import { Common } from '@ethereumjs/common' import { RLP } from 'rlp' @@ -176,7 +178,7 @@ export class DefaultStateManager extends BaseStateManager implements StateManage // from storage cache const addressHex = address.buf.toString('hex') let storageTrie = this._storageTries[addressHex] - if (!storageTrie) { + if (isFalsy(storageTrie)) { // lookup from state storageTrie = await this._lookupStorageTrie(address) } @@ -251,7 +253,7 @@ export class DefaultStateManager extends BaseStateManager implements StateManage value = unpadBuffer(value) await this._modifyContractStorage(address, async (storageTrie, done) => { - if (value && value.length) { + if (isTruthy(value) && value.length) { // format input const encodedValue = Buffer.from(RLP.encode(Uint8Array.from(value))) if (this.DEBUG) { @@ -496,7 +498,7 @@ export class DefaultStateManager extends BaseStateManager implements StateManage */ async accountExists(address: Address): Promise { const account = this._cache.lookup(address) - if (account && !(account as any).virtual && !this._cache.keyIsDeleted(address)) { + if (account && isFalsy((account as any).virtual) && !this._cache.keyIsDeleted(address)) { return true } if (await this._trie.get(address.buf)) { diff --git a/packages/trie/src/db/level.ts b/packages/trie/src/db/level.ts index f15985a08d..93481fb33d 100644 --- a/packages/trie/src/db/level.ts +++ b/packages/trie/src/db/level.ts @@ -1,4 +1,5 @@ // eslint-disable-next-line implicit-dependencies/no-implicit +import { isTruthy } from '@ethereumjs/util' import { AbstractLevel } from 'abstract-level' import { MemoryLevel } from 'memory-level' import { BatchDBOp, DB } from '../types' @@ -31,7 +32,7 @@ export class LevelDB implements DB { try { value = await this._leveldb.get(key, ENCODING_OPTS) } catch (error: any) { - if (error.notFound) { + if (isTruthy(error.notFound)) { // not found, returning null } else { throw error diff --git a/packages/trie/src/trie/secure.ts b/packages/trie/src/trie/secure.ts index 247e9d760a..ecad4270cc 100644 --- a/packages/trie/src/trie/secure.ts +++ b/packages/trie/src/trie/secure.ts @@ -1,6 +1,7 @@ import { keccak256 } from 'ethereum-cryptography/keccak' import { CheckpointTrie } from './checkpoint' import { Proof } from '../types' +import { isFalsy } from '@ethereumjs/util' /** * You can create a secure Trie where the keys are automatically hashed @@ -29,7 +30,7 @@ export class SecureTrie extends CheckpointTrie { * @param value */ async put(key: Buffer, val: Buffer): Promise { - if (!val || val.toString() === '') { + if (isFalsy(val) || val.toString() === '') { await this.del(key) } else { const hash = Buffer.from(keccak256(key)) diff --git a/packages/trie/src/trie/trie.ts b/packages/trie/src/trie/trie.ts index 220fd237a6..c8f0f01d99 100644 --- a/packages/trie/src/trie/trie.ts +++ b/packages/trie/src/trie/trie.ts @@ -1,6 +1,6 @@ import Semaphore from 'semaphore-async-await' import { keccak256 } from 'ethereum-cryptography/keccak' -import { KECCAK256_RLP } from '@ethereumjs/util' +import { isFalsy, isTruthy, KECCAK256_RLP } from '@ethereumjs/util' import { DB, BatchDBOp, PutBatch, TrieNode, Nibbles, EmbeddedNode } from '../types' import { LevelDB } from '../db' import { TrieReadStream as ReadStream } from '../util/readStream' @@ -52,7 +52,7 @@ export class Trie { * Sets the current root of the `trie` */ set root(value: Buffer) { - if (!value) { + if (isFalsy(value)) { value = this.EMPTY_TRIE_ROOT } if (value.length !== 32) throw new Error('Invalid root length. Roots are 32 bytes') @@ -113,7 +113,7 @@ export class Trie { */ async put(key: Buffer, value: Buffer): Promise { // If value is empty, delete - if (!value || value.toString() === '') { + if (isFalsy(value) || value.toString() === '') { return await this.del(key) } @@ -375,9 +375,9 @@ export class Trie { stack: TrieNode[] ) => { // branchNode is the node ON the branch node not THE branch node - if (!parentNode || parentNode instanceof BranchNode) { + if (isFalsy(parentNode) || parentNode instanceof BranchNode) { // branch->? - if (parentNode) { + if (isTruthy(parentNode)) { stack.push(parentNode) } @@ -425,7 +425,7 @@ export class Trie { } let lastNode = stack.pop() as TrieNode - if (!lastNode) throw new Error('missing last node') + if (isFalsy(lastNode)) throw new Error('missing last node') let parentNode = stack.pop() const opStack: BatchDBOp[] = [] @@ -583,7 +583,7 @@ export class Trie { async batch(ops: BatchDBOp[]): Promise { for (const op of ops) { if (op.type === 'put') { - if (!op.value) { + if (isFalsy(op.value)) { throw new Error('Invalid batch db operation') } await this.put(op.key, op.value) @@ -609,7 +609,7 @@ export class Trie { if (!trie) { trie = new Trie() - if (opStack[0]) { + if (isTruthy(opStack[0])) { trie.root = opStack[0].key } } diff --git a/packages/trie/test/official.spec.ts b/packages/trie/test/official.spec.ts index a31c1518d7..dbe7783522 100644 --- a/packages/trie/test/official.spec.ts +++ b/packages/trie/test/official.spec.ts @@ -1,3 +1,4 @@ +import { isTruthy } from '@ethereumjs/util' import * as tape from 'tape' import { CheckpointTrie, LevelDB } from '../src' @@ -11,9 +12,9 @@ tape('official tests', async function (t) { const expect = jsonTests[testName].root for (const input of inputs) { for (let i = 0; i < 2; i++) { - if (input[i] && input[i].slice(0, 2) === '0x') { + if (isTruthy(input[i]) && input[i].slice(0, 2) === '0x') { input[i] = Buffer.from(input[i].slice(2), 'hex') - } else if (input[i] && typeof input[i] === 'string') { + } else if (isTruthy(input[i]) && typeof input[i] === 'string') { input[i] = Buffer.from(input[i]) } await trie.put(Buffer.from(input[0]), input[1]) @@ -40,7 +41,7 @@ tape('official tests any order', async function (t) { key = Buffer.from(key.slice(2), 'hex') } - if (val && val.slice(0, 2) === '0x') { + if (isTruthy(val) && val.slice(0, 2) === '0x') { val = Buffer.from(val.slice(2), 'hex') } diff --git a/packages/trie/test/trie/secure.spec.ts b/packages/trie/test/trie/secure.spec.ts index 3067412d99..c73c6ab0ae 100644 --- a/packages/trie/test/trie/secure.spec.ts +++ b/packages/trie/test/trie/secure.spec.ts @@ -1,3 +1,4 @@ +import { isTruthy } from '@ethereumjs/util' import * as tape from 'tape' import { LevelDB, SecureTrie } from '../../src' @@ -38,7 +39,7 @@ tape('SecureTrie', function (t) { it.test('empty values', async function (t) { for (const row of jsonTests.emptyValues.in) { - const val = row[1] ? Buffer.from(row[1]) : (null as unknown as Buffer) + const val = isTruthy(row[1]) ? Buffer.from(row[1]) : (null as unknown as Buffer) await trie.put(Buffer.from(row[0]), val) } t.equal('0x' + trie.root.toString('hex'), jsonTests.emptyValues.root) @@ -48,7 +49,7 @@ tape('SecureTrie', function (t) { it.test('branchingTests', async function (t) { trie = new SecureTrie({ db: new LevelDB() }) for (const row of jsonTests.branchingTests.in) { - const val = row[1] ? Buffer.from(row[1]) : (null as unknown as Buffer) + const val = isTruthy(row[1]) ? Buffer.from(row[1]) : (null as unknown as Buffer) await trie.put(Buffer.from(row[0]), val) } t.equal('0x' + trie.root.toString('hex'), jsonTests.branchingTests.root) @@ -58,7 +59,7 @@ tape('SecureTrie', function (t) { it.test('jeff', async function (t) { for (const row of jsonTests.jeff.in) { let val = row[1] - if (val) { + if (isTruthy(val)) { val = Buffer.from(row[1].slice(2), 'hex') } await trie.put(Buffer.from(row[0].slice(2), 'hex'), val) diff --git a/packages/tx/src/baseTransaction.ts b/packages/tx/src/baseTransaction.ts index 41ffdf5e2a..d20e0f9e14 100644 --- a/packages/tx/src/baseTransaction.ts +++ b/packages/tx/src/baseTransaction.ts @@ -1,4 +1,5 @@ import { Chain, Common, Hardfork } from '@ethereumjs/common' +import { isTruthy } from '@ethereumjs/util' import { Address, BigIntLike, @@ -359,7 +360,7 @@ export abstract class BaseTransaction { */ protected _getCommon(common?: Common, chainId?: BigIntLike) { // Chain ID provided - if (chainId) { + if (isTruthy(chainId)) { const chainIdBigInt = bufferToBigInt(toBuffer(chainId)) if (common) { if (common.chainId() !== chainIdBigInt) { diff --git a/packages/tx/src/eip1559Transaction.ts b/packages/tx/src/eip1559Transaction.ts index 7977768ea2..78d590d4fe 100644 --- a/packages/tx/src/eip1559Transaction.ts +++ b/packages/tx/src/eip1559Transaction.ts @@ -150,7 +150,7 @@ export class FeeMarketEIP1559Transaction extends BaseTransaction boolean = falsePredicate, directory: string, excludeDir: RegExp | string[] = [] ): Promise { @@ -52,7 +52,7 @@ export async function getTests( const testsByName = JSON.parse(content) const testNames = Object.keys(testsByName) for (const testName of testNames) { - if (!skipPredicate(testName, testsByName[testName])) { + if (skipPredicate(testName, testsByName[testName]) === false) { await onFile(parsedFileName, subDir, testName, testsByName[testName]) } } diff --git a/packages/tx/test/transactionRunner.ts b/packages/tx/test/transactionRunner.ts index 238cf6434b..2e2e0a3ac6 100644 --- a/packages/tx/test/transactionRunner.ts +++ b/packages/tx/test/transactionRunner.ts @@ -5,6 +5,7 @@ import { Common } from '@ethereumjs/common' import { TransactionFactory } from '../src' import { ForkName, ForkNamesMap, OfficialTransactionTestData } from './types' import { getTests } from './testLoader' +import { isTruthy } from '@ethereumjs/util' const argv = minimist(process.argv.slice(2)) const file: string | undefined = argv.file @@ -42,7 +43,7 @@ const EIPs: any = { } tape('TransactionTests', async (t) => { - const fileFilterRegex = file ? new RegExp(file + '[^\\w]') : undefined + const fileFilterRegex = isTruthy(file) ? new RegExp(file + '[^\\w]') : undefined await getTests( ( _filename: string, @@ -56,14 +57,14 @@ tape('TransactionTests', async (t) => { continue } const forkTestData = testData.result[forkName] - const shouldBeInvalid = !!forkTestData.exception + const shouldBeInvalid = isTruthy(forkTestData.exception) try { const rawTx = toBuffer(testData.txbytes) const hardfork = forkNameMap[forkName] const common = new Common({ chain: 1, hardfork }) const activateEIPs = EIPs[forkName] - if (activateEIPs) { + if (isTruthy(activateEIPs)) { common.setEIPs(activateEIPs) } const tx = TransactionFactory.fromSerializedData(rawTx, { common }) @@ -73,7 +74,7 @@ tape('TransactionTests', async (t) => { const senderIsCorrect = forkTestData.sender === sender const hashIsCorrect = forkTestData.hash?.slice(2) === hash - const hashAndSenderAreCorrect = forkTestData && senderIsCorrect && hashIsCorrect + const hashAndSenderAreCorrect = senderIsCorrect && hashIsCorrect if (shouldBeInvalid) { st.assert(!txIsValid, `Transaction should be invalid on ${forkName}`) } else { diff --git a/packages/util/src/account.ts b/packages/util/src/account.ts index 9cc3c17f48..5e3f85a46b 100644 --- a/packages/util/src/account.ts +++ b/packages/util/src/account.ts @@ -14,7 +14,7 @@ import { zeros, } from './bytes' import { assertIsString, assertIsHexString, assertIsBuffer } from './helpers' -import { BigIntLike, BufferLike } from './types' +import { BigIntLike, BufferLike, isTruthy } from './types' const _0n = BigInt(0) @@ -35,10 +35,10 @@ export class Account { const { nonce, balance, stateRoot, codeHash } = accountData return new Account( - nonce ? bufferToBigInt(toBuffer(nonce)) : undefined, - balance ? bufferToBigInt(toBuffer(balance)) : undefined, - stateRoot ? toBuffer(stateRoot) : undefined, - codeHash ? toBuffer(codeHash) : undefined + isTruthy(nonce) ? bufferToBigInt(toBuffer(nonce)) : undefined, + isTruthy(balance) ? bufferToBigInt(toBuffer(balance)) : undefined, + isTruthy(stateRoot) ? toBuffer(stateRoot) : undefined, + isTruthy(codeHash) ? toBuffer(codeHash) : undefined ) } @@ -155,7 +155,7 @@ export const toChecksumAddress = function ( const address = stripHexPrefix(hexAddress).toLowerCase() let prefix = '' - if (eip1191ChainId) { + if (isTruthy(eip1191ChainId)) { const chainId = bufferToBigInt(toBuffer(eip1191ChainId)) prefix = chainId.toString() + '0x' } diff --git a/packages/util/src/internal.ts b/packages/util/src/internal.ts index 52032f54ca..ab2ed387ce 100644 --- a/packages/util/src/internal.ts +++ b/packages/util/src/internal.ts @@ -102,7 +102,7 @@ export function arrayContainsArray( ) } - return subset[some ? 'some' : 'every']((value) => superset.indexOf(value) >= 0) + return subset[some === true ? 'some' : 'every']((value) => superset.indexOf(value) >= 0) } /** @@ -182,7 +182,7 @@ export function getKeys(params: Record[], key: string, allowEmpt for (let i = 0; i < params.length; i++) { let value = params[i][key] - if (allowEmpty && !value) { + if (allowEmpty === true && !value) { value = '' } else if (typeof value !== 'string') { throw new Error(`invalid abi - expected type 'string', received ${typeof value}`) @@ -203,7 +203,7 @@ export function getKeys(params: Record[], key: string, allowEmpt export function isHexString(value: string, length?: number): boolean { if (typeof value !== 'string' || !value.match(/^0x[0-9A-Fa-f]*$/)) return false - if (length && value.length !== 2 + 2 * length) return false + if (typeof length !== 'undefined' && length > 0 && value.length !== 2 + 2 * length) return false return true } diff --git a/packages/util/src/types.ts b/packages/util/src/types.ts index f1a620c8af..dec3e5b8ab 100644 --- a/packages/util/src/types.ts +++ b/packages/util/src/types.ts @@ -118,3 +118,35 @@ export function toType( throw new Error('unknown outputType') } } + +type Falsy = false | '' | 0 | null | undefined | 0n + +/** + * Returns true if a value is falsy + * + * @param value - Value to check for falseness + * + * @deprecated This helper function should only be used temporarily until the monorepo types are explicit enough + */ +export function isFalsy(value: unknown): value is Falsy { + return !!( + value === false || + value === '' || + value === 0 || + Number.isNaN(value) || + value === null || + typeof value === 'undefined' || + value === BigInt(0) + ) +} + +/** + * Returns true if a value is truthy + * + * @param value - Value to check for truthiness + * + * @deprecated This helper function should only be used temporarily until the monorepo types are explicit enough + */ +export function isTruthy(value: T | Falsy): value is T { + return !isFalsy(value) +} diff --git a/packages/util/test/types.spec.ts b/packages/util/test/types.spec.ts index 5d3c8a8bce..dca12f4b35 100644 --- a/packages/util/test/types.spec.ts +++ b/packages/util/test/types.spec.ts @@ -9,6 +9,8 @@ import { bigIntToHex, bigIntToBuffer, bufferToBigInt, + isFalsy, + isTruthy, } from '../src' tape('toType', function (t) { @@ -134,3 +136,35 @@ tape('toType', function (t) { }) }) }) + +tape('isFalsy and isTruthy', function (t) { + const falsyValues = [false, '', 0, NaN, null, undefined, BigInt(0)] + const truthyValues = [true, 'test', -1, 1, BigInt(1), [], {}] + t.test('isFalsy should return true for all falsy values', function (st) { + falsyValues.forEach((falsyValue) => { + st.ok(isFalsy(falsyValue) === true) + }) + st.end() + }) + + t.test('isFalsy should return false for truthy values', function (st) { + truthyValues.forEach((truthyValue) => { + st.ok(isFalsy(truthyValue) === false) + }) + st.end() + }) + + t.test('isTruthy should return false for all falsy values', function (st) { + falsyValues.forEach((falsyValue) => { + st.ok(isTruthy(falsyValue) === false) + }) + st.end() + }) + + t.test('isTruthy should return true for truthy values', function (st) { + truthyValues.forEach((truthyValue) => { + st.ok(isTruthy(truthyValue) === true) + }) + st.end() + }) +}) diff --git a/packages/vm/src/bloom/index.ts b/packages/vm/src/bloom/index.ts index 14bc1faa76..3c9b7409b9 100644 --- a/packages/vm/src/bloom/index.ts +++ b/packages/vm/src/bloom/index.ts @@ -1,5 +1,5 @@ import { keccak256 } from 'ethereum-cryptography/keccak' -import { zeros } from '@ethereumjs/util' +import { isTruthy, zeros } from '@ethereumjs/util' const BYTE_SIZE = 256 @@ -67,7 +67,7 @@ export class Bloom { * Bitwise or blooms together. */ or(bloom: Bloom) { - if (bloom) { + if (isTruthy(bloom)) { for (let i = 0; i <= BYTE_SIZE; i++) { this.bitvector[i] = this.bitvector[i] | bloom.bitvector[i] } diff --git a/packages/vm/src/buildBlock.ts b/packages/vm/src/buildBlock.ts index b62f4e641a..3ef8afb4af 100644 --- a/packages/vm/src/buildBlock.ts +++ b/packages/vm/src/buildBlock.ts @@ -1,4 +1,4 @@ -import { Address, toBuffer, toType, TypeOutput } from '@ethereumjs/util' +import { Address, isTruthy, toBuffer, toType, TypeOutput } from '@ethereumjs/util' import { Trie } from '@ethereumjs/trie' import { RLP } from 'rlp' import { Block, HeaderData } from '@ethereumjs/block' @@ -39,7 +39,10 @@ export class BlockBuilder { gasLimit: opts.headerData?.gasLimit ?? opts.parentBlock.header.gasLimit, } - if (this.vm._common.isActivatedEIP(1559) && this.headerData.baseFeePerGas === undefined) { + if ( + this.vm._common.isActivatedEIP(1559) === true && + typeof this.headerData.baseFeePerGas === 'undefined' + ) { this.headerData.baseFeePerGas = opts.parentBlock.header.calcNextBaseFee() } } @@ -98,7 +101,7 @@ export class BlockBuilder { private async rewardMiner() { const minerReward = this.vm._common.param('pow', 'minerReward') const reward = calculateMinerReward(minerReward, 0) - const coinbase = this.headerData.coinbase + const coinbase = isTruthy(this.headerData.coinbase) ? new Address(toBuffer(this.headerData.coinbase)) : Address.zero() await rewardAccount(this.vm.eei, coinbase, reward) @@ -198,7 +201,7 @@ export class BlockBuilder { const blockData = { header: headerData, transactions: this.transactions } const block = Block.fromBlockData(blockData, blockOpts) - if (this.blockOpts.putBlockIntoBlockchain) { + if (this.blockOpts.putBlockIntoBlockchain === true) { await this.vm.blockchain.putBlock(block) } diff --git a/packages/vm/src/eei/vmState.ts b/packages/vm/src/eei/vmState.ts index 55852cb6b8..c074ef6fdb 100644 --- a/packages/vm/src/eei/vmState.ts +++ b/packages/vm/src/eei/vmState.ts @@ -1,6 +1,6 @@ import { Chain, Common, Hardfork } from '@ethereumjs/common' import { AccessList, AccessListItem } from '@ethereumjs/tx' -import { Account, Address, toBuffer } from '@ethereumjs/util' +import { Account, Address, isTruthy, toBuffer } from '@ethereumjs/util' const Set = require('core-js-pure/es/set') import { StateManager, AccountFields } from '@ethereumjs/statemanager' @@ -49,7 +49,7 @@ export class VmState implements EVMStateAccess { this._accessedStorageReverted = [new Map()] // Safeguard if "process" is not available (browser) - if (process !== undefined && process.env.DEBUG) { + if (typeof process?.env.DEBUG !== 'undefined') { this.DEBUG = true } this._debug = createDebugLogger('vm:state') @@ -216,7 +216,7 @@ export class VmState implements EVMStateAccess { ) { const mapTarget = storageList[storageList.length - 1] - if (mapTarget) { + if (isTruthy(mapTarget)) { // Note: storageMap is always defined here per definition (TypeScript cannot infer this) storageMap?.forEach((slotSet: Set, addressString: string) => { const addressExists = mapTarget.get(addressString) @@ -256,10 +256,10 @@ export class VmState implements EVMStateAccess { const [balance, code, storage] = state const account = Account.fromAccountData({ balance }) await this.putAccount(addr, account) - if (code) { + if (isTruthy(code)) { await this.putContractCode(addr, toBuffer(code)) } - if (storage) { + if (isTruthy(storage)) { for (const [key, value] of storage) { await this.putContractStorage(addr, toBuffer(key), toBuffer(value)) } @@ -274,7 +274,7 @@ export class VmState implements EVMStateAccess { * as defined in EIP-161 (https://eips.ethereum.org/EIPS/eip-161). */ async cleanupTouchedAccounts(): Promise { - if (this._common.gteHardfork('spuriousDragon')) { + if (this._common.gteHardfork(Hardfork.SpuriousDragon) === true) { const touchedArray = Array.from(this._touched) for (const addressHex of touchedArray) { const address = new Address(Buffer.from(addressHex, 'hex')) diff --git a/packages/vm/src/runBlock.ts b/packages/vm/src/runBlock.ts index 8173c9eb8f..e7ee43e889 100644 --- a/packages/vm/src/runBlock.ts +++ b/packages/vm/src/runBlock.ts @@ -1,6 +1,14 @@ import { debug as createDebugLogger } from 'debug' import { Trie } from '@ethereumjs/trie' -import { Account, Address, bigIntToBuffer, bufArrToArr, intToBuffer, short } from '@ethereumjs/util' +import { + Account, + Address, + bigIntToBuffer, + bufArrToArr, + intToBuffer, + isTruthy, + short, +} from '@ethereumjs/util' import { RLP } from 'rlp' import { Block } from '@ethereumjs/block' import { ConsensusType, Hardfork } from '@ethereumjs/common' @@ -30,7 +38,7 @@ export async function runBlock(this: VM, opts: RunBlockOpts): Promise= BigInt('0x8000000000000000')) { const msg = _errorMsg('Invalid block with gas limit greater than (2^63 - 1)', this, block) throw new Error(msg) @@ -254,7 +262,7 @@ async function applyTransactions(this: VM, block: Block, opts: RunBlockOpts) { const tx = block.transactions[txIdx] let maxGasLimit - if (this._common.isActivatedEIP(1559)) { + if (this._common.isActivatedEIP(1559) === true) { maxGasLimit = block.header.gasLimit * this._common.param('gasConfig', 'elasticityMultiplier') } else { maxGasLimit = block.header.gasLimit @@ -395,7 +403,7 @@ export function encodeReceipt(receipt: TxReceipt, txType: number) { */ async function _applyDAOHardfork(state: EVMStateAccess) { const DAORefundContractAddress = new Address(Buffer.from(DAORefundContract, 'hex')) - if (!state.accountExists(DAORefundContractAddress)) { + if ((await state.accountExists(DAORefundContractAddress)) === false) { await state.putAccount(DAORefundContractAddress, new Account()) } const DAORefundAccount = await state.getAccount(DAORefundContractAddress) diff --git a/packages/vm/src/runTx.ts b/packages/vm/src/runTx.ts index 6eb922e689..070b8d4279 100644 --- a/packages/vm/src/runTx.ts +++ b/packages/vm/src/runTx.ts @@ -1,5 +1,5 @@ import { debug as createDebugLogger } from 'debug' -import { Address, KECCAK256_NULL, toBuffer, short } from '@ethereumjs/util' +import { Address, KECCAK256_NULL, toBuffer, short, isFalsy } from '@ethereumjs/util' import { Block } from '@ethereumjs/block' import { ConsensusType, Hardfork } from '@ethereumjs/common' import { @@ -30,7 +30,7 @@ const debugGas = createDebugLogger('vm:tx:gas') */ export async function runTx(this: VM, opts: RunTxOpts): Promise { // tx is required - if (!opts.tx) { + if (isFalsy(opts.tx)) { throw new Error('invalid input, tx is required') } @@ -44,7 +44,7 @@ export async function runTx(this: VM, opts: RunTxOpts): Promise { const state = this.eei - if (opts.reportAccessList && !('generateAccessList' in state)) { + if (opts.reportAccessList === true && !('generateAccessList' in state)) { const msg = _errorMsg( 'reportAccessList needs a StateManager implementing the generateAccessList() method', this, @@ -55,7 +55,7 @@ export async function runTx(this: VM, opts: RunTxOpts): Promise { } // Ensure we start with a clear warmed accounts Map - if (this._common.isActivatedEIP(2929)) { + if (this._common.isActivatedEIP(2929) === true) { state.clearWarmedAccounts() } @@ -66,9 +66,12 @@ export async function runTx(this: VM, opts: RunTxOpts): Promise { } // Typed transaction specific setup tasks - if (opts.tx.supports(Capability.EIP2718TypedTransaction) && this._common.isActivatedEIP(2718)) { + if ( + opts.tx.supports(Capability.EIP2718TypedTransaction) && + this._common.isActivatedEIP(2718) === true + ) { // Is it an Access List transaction? - if (!this._common.isActivatedEIP(2930)) { + if (this._common.isActivatedEIP(2930) === false) { await state.revert() const msg = _errorMsg( 'Cannot run transaction: EIP 2930 is not activated.', @@ -78,7 +81,7 @@ export async function runTx(this: VM, opts: RunTxOpts): Promise { ) throw new Error(msg) } - if (opts.reportAccessList && !('generateAccessList' in state)) { + if (opts.reportAccessList === true && !('generateAccessList' in state)) { await state.revert() const msg = _errorMsg( 'StateManager needs to implement generateAccessList() when running with reportAccessList option', @@ -88,7 +91,10 @@ export async function runTx(this: VM, opts: RunTxOpts): Promise { ) throw new Error(msg) } - if (opts.tx.supports(Capability.EIP1559FeeMarket) && !this._common.isActivatedEIP(1559)) { + if ( + opts.tx.supports(Capability.EIP1559FeeMarket) && + this._common.isActivatedEIP(1559) === false + ) { await state.revert() const msg = _errorMsg( 'Cannot run transaction: EIP 1559 is not activated.', @@ -116,7 +122,7 @@ export async function runTx(this: VM, opts: RunTxOpts): Promise { if (this.DEBUG) { debug(`tx checkpoint committed`) } - if (this._common.isActivatedEIP(2929) && opts.reportAccessList) { + if (this._common.isActivatedEIP(2929) === true && opts.reportAccessList === true) { const { tx } = opts // Do not include sender address in access list const removed = [tx.getSenderAddress()] @@ -138,7 +144,7 @@ export async function runTx(this: VM, opts: RunTxOpts): Promise { } throw e } finally { - if (this._common.isActivatedEIP(2929)) { + if (this._common.isActivatedEIP(2929) === true) { state.clearWarmedAccounts() } } @@ -171,7 +177,7 @@ async function _runTx(this: VM, opts: RunTxOpts): Promise { ) } - if (this._common.isActivatedEIP(2929)) { + if (this._common.isActivatedEIP(2929) === true) { // Add origin and precompiles to warm addresses const activePrecompiles = this.evm.precompiles for (const [addressStr] of activePrecompiles.entries()) { @@ -182,7 +188,7 @@ async function _runTx(this: VM, opts: RunTxOpts): Promise { // Note: in case we create a contract, we do this in EVMs `_executeCreate` (this is also correct in inner calls, per the EIP) state.addWarmedAddress(tx.to.buf) } - if (this._common.isActivatedEIP(3651)) { + if (this._common.isActivatedEIP(3651) === true) { state.addWarmedAddress(block.header.coinbase.buf) } } @@ -199,7 +205,7 @@ async function _runTx(this: VM, opts: RunTxOpts): Promise { debugGas(`Subtracting base fee (${txBaseFee}) from gasLimit (-> ${gasLimit})`) } - if (this._common.isActivatedEIP(1559)) { + if (this._common.isActivatedEIP(1559) === true) { // EIP-1559 spec: // Ensure that the user was willing to at least pay the base fee // assert transaction.max_fee_per_gas >= block.base_fee_per_gas @@ -221,13 +227,13 @@ async function _runTx(this: VM, opts: RunTxOpts): Promise { const { nonce, balance } = fromAccount // EIP-3607: Reject transactions from senders with deployed code - if (this._common.isActivatedEIP(3607) && !fromAccount.codeHash.equals(KECCAK256_NULL)) { + if (this._common.isActivatedEIP(3607) === true && !fromAccount.codeHash.equals(KECCAK256_NULL)) { const msg = _errorMsg('invalid sender address, address is not EOA (EIP-3607)', this, block, tx) throw new Error(msg) } const cost = tx.getUpfrontCost(block.header.baseFeePerGas) - if (opts.skipBalance) { + if (opts.skipBalance === true) { // if skipBalance, add tx cost to sender balance to ensure sufficient funds fromAccount.balance += cost await this.stateManager.putAccount(caller, fromAccount) @@ -258,7 +264,7 @@ async function _runTx(this: VM, opts: RunTxOpts): Promise { } } } - if (!opts.skipNonce) { + if (opts.skipNonce !== true) { if (nonce !== tx.nonce) { const msg = _errorMsg( `the tx doesn't have the correct nonce. account has nonce of: ${nonce} tx has nonce of: ${tx.nonce}`, @@ -285,7 +291,7 @@ async function _runTx(this: VM, opts: RunTxOpts): Promise { } else { // Have to cast as legacy tx since EIP1559 tx does not have gas price gasPrice = (tx).gasPrice - if (this._common.isActivatedEIP(1559)) { + if (this._common.isActivatedEIP(1559) === true) { const baseFee = block.header.baseFeePerGas! inclusionFeePerGas = (tx).gasPrice - baseFee } @@ -295,7 +301,7 @@ async function _runTx(this: VM, opts: RunTxOpts): Promise { fromAccount.nonce += BigInt(1) const txCost = tx.gasLimit * gasPrice fromAccount.balance -= txCost - if (opts.skipBalance && fromAccount.balance < BigInt(0)) { + if (opts.skipBalance === true && fromAccount.balance < BigInt(0)) { fromAccount.balance = BigInt(0) } await state.putAccount(caller, fromAccount) @@ -395,7 +401,7 @@ async function _runTx(this: VM, opts: RunTxOpts): Promise { const minerAccount = await state.getAccount(miner) // add the amount spent on gas to the miner's account - if (this._common.isActivatedEIP(1559)) { + if (this._common.isActivatedEIP(1559) === true) { minerAccount.balance += results.totalGasSpent * inclusionFeePerGas! } else { minerAccount.balance += results.amountSpent @@ -504,7 +510,7 @@ export async function generateTxReceipt( if (!tx.supports(Capability.EIP2718TypedTransaction)) { // Legacy transaction - if (this._common.gteHardfork(Hardfork.Byzantium)) { + if (this._common.gteHardfork(Hardfork.Byzantium) === true) { // Post-Byzantium receipt = { status: txResult.execResult.exceptionError ? 0 : 1, // Receipts have a 0 as status on error diff --git a/packages/vm/src/vm.ts b/packages/vm/src/vm.ts index 8f809e4896..ef889784af 100644 --- a/packages/vm/src/vm.ts +++ b/packages/vm/src/vm.ts @@ -1,4 +1,4 @@ -import { Account, Address, toType, TypeOutput } from '@ethereumjs/util' +import { Account, Address, isTruthy, toType, TypeOutput } from '@ethereumjs/util' import { Blockchain } from '@ethereumjs/blockchain' import { Chain, Common } from '@ethereumjs/common' import { StateManager, DefaultStateManager } from '@ethereumjs/statemanager' @@ -129,7 +129,7 @@ export class VM extends AsyncEventEmitter { this._hardforkByTD = toType(opts.hardforkByTD, TypeOutput.BigInt) // Safeguard if "process" is not available (browser) - if (process !== undefined && process.env.DEBUG) { + if (typeof process?.env.DEBUG !== 'undefined') { this.DEBUG = true } @@ -143,12 +143,12 @@ export class VM extends AsyncEventEmitter { await (this.blockchain as any)._init() if (!this._opts.stateManager) { - if (this._opts.activateGenesisState) { + if (this._opts.activateGenesisState === true) { await this.eei.generateCanonicalGenesis(this.blockchain.genesisState()) } } - if (this._opts.activatePrecompiles && !this._opts.stateManager) { + if (this._opts.activatePrecompiles === true && typeof this._opts.stateManager === 'undefined') { await this.eei.checkpoint() // put 1 wei in each of the precompiles in order to make the accounts non-empty and thus not have them deduct `callNewAccount` gas. for (const [addressStr] of getActivePrecompiles(this._common)) { @@ -224,7 +224,7 @@ export class VM extends AsyncEventEmitter { evm: evmCopy, eei: eeiCopy, hardforkByBlockNumber: this._hardforkByBlockNumber ? true : undefined, - hardforkByTD: this._hardforkByTD ? this._hardforkByTD : undefined, + hardforkByTD: isTruthy(this._hardforkByTD) ? this._hardforkByTD : undefined, }) } diff --git a/packages/vm/tests/api/EIPs/eip-2315.spec.ts b/packages/vm/tests/api/EIPs/eip-2315.spec.ts index 99a5e664dc..e7090c212c 100644 --- a/packages/vm/tests/api/EIPs/eip-2315.spec.ts +++ b/packages/vm/tests/api/EIPs/eip-2315.spec.ts @@ -11,7 +11,7 @@ tape('Berlin: EIP 2315 tests', (t) => { const vm = await VM.create({ common }) ;(vm.evm).on('step', function (step: any) { - if (test.steps.length) { + if (test.steps.length > 0) { st.equal(step.pc, test.steps[i].expectedPC) st.equal(step.opcode.name, test.steps[i].expectedOpcode) } diff --git a/packages/vm/tests/api/EIPs/eip-2929.spec.ts b/packages/vm/tests/api/EIPs/eip-2929.spec.ts index 7b26b4c456..bd8e6d3874 100644 --- a/packages/vm/tests/api/EIPs/eip-2929.spec.ts +++ b/packages/vm/tests/api/EIPs/eip-2929.spec.ts @@ -24,7 +24,7 @@ tape('EIP 2929: gas cost tests', (t) => { const gasUsed = currentGas - step.gasLeft currentGas = step.gasLeft - if (test.steps.length) { + if (test.steps.length > 0) { st.equal( step.opcode.name, test.steps[i].expectedOpcode, diff --git a/packages/vm/tests/api/EIPs/eip-3074-authcall.spec.ts b/packages/vm/tests/api/EIPs/eip-3074-authcall.spec.ts index 3bc1d1ea23..554c54a591 100644 --- a/packages/vm/tests/api/EIPs/eip-3074-authcall.spec.ts +++ b/packages/vm/tests/api/EIPs/eip-3074-authcall.spec.ts @@ -6,6 +6,7 @@ import { bufferToBigInt, ECDSASignature, ecsign, + isTruthy, privateToAddress, setLengthLeft, toBuffer, @@ -169,24 +170,30 @@ function MSTORE(position: Buffer, value: Buffer) { */ function getAuthCallCode(data: AuthcallData) { const ZEROS32 = zeros(32) - const gasLimitBuffer = setLengthLeft(data.gasLimit ? bigIntToBuffer(data.gasLimit) : ZEROS32, 32) + const gasLimitBuffer = setLengthLeft( + isTruthy(data.gasLimit) ? bigIntToBuffer(data.gasLimit) : ZEROS32, + 32 + ) const addressBuffer = setLengthLeft(data.address.buf, 32) - const valueBuffer = setLengthLeft(data.value ? bigIntToBuffer(data.value) : ZEROS32, 32) - const valueExtBuffer = setLengthLeft(data.valueExt ? bigIntToBuffer(data.valueExt) : ZEROS32, 32) + const valueBuffer = setLengthLeft(isTruthy(data.value) ? bigIntToBuffer(data.value) : ZEROS32, 32) + const valueExtBuffer = setLengthLeft( + isTruthy(data.valueExt) ? bigIntToBuffer(data.valueExt) : ZEROS32, + 32 + ) const argsOffsetBuffer = setLengthLeft( - data.argsOffset ? bigIntToBuffer(data.argsOffset) : ZEROS32, + isTruthy(data.argsOffset) ? bigIntToBuffer(data.argsOffset) : ZEROS32, 32 ) const argsLengthBuffer = setLengthLeft( - data.argsLength ? bigIntToBuffer(data.argsLength) : ZEROS32, + isTruthy(data.argsLength) ? bigIntToBuffer(data.argsLength) : ZEROS32, 32 ) const retOffsetBuffer = setLengthLeft( - data.retOffset ? bigIntToBuffer(data.retOffset) : ZEROS32, + isTruthy(data.retOffset) ? bigIntToBuffer(data.retOffset) : ZEROS32, 32 ) const retLengthBuffer = setLengthLeft( - data.retLength ? bigIntToBuffer(data.retLength) : ZEROS32, + isTruthy(data.retLength) ? bigIntToBuffer(data.retLength) : ZEROS32, 32 ) const PUSH32 = Buffer.from('7f', 'hex') diff --git a/packages/vm/tests/api/EIPs/eip-3607.spec.ts b/packages/vm/tests/api/EIPs/eip-3607.spec.ts index 0969bfc4b3..47c854768b 100644 --- a/packages/vm/tests/api/EIPs/eip-3607.spec.ts +++ b/packages/vm/tests/api/EIPs/eip-3607.spec.ts @@ -18,7 +18,7 @@ tape('EIP-3607 tests', (t) => { await vm.runTx({ tx }) st.fail('runTx should have thrown') } catch (error: any) { - if (error.message.includes('EIP-3607')) { + if ((error.message as string).includes('EIP-3607')) { st.pass('threw correct error') } else { st.fail('did not throw correct error') diff --git a/packages/vm/tests/api/EIPs/eip-3855.spec.ts b/packages/vm/tests/api/EIPs/eip-3855.spec.ts index 5955ea4b65..736d908d61 100644 --- a/packages/vm/tests/api/EIPs/eip-3855.spec.ts +++ b/packages/vm/tests/api/EIPs/eip-3855.spec.ts @@ -17,7 +17,7 @@ tape('EIP 3541 tests', (t) => { const vm = await VM.create({ common }) let stack: bigint[] ;(vm.evm).on('step', (e: InterpreterStep) => { - if (stack) { + if (typeof stack !== 'undefined') { st.fail('should only do PUSH0 once') } stack = e.stack diff --git a/packages/vm/tests/api/buildBlock.spec.ts b/packages/vm/tests/api/buildBlock.spec.ts index f947047d10..dae0b53e95 100644 --- a/packages/vm/tests/api/buildBlock.spec.ts +++ b/packages/vm/tests/api/buildBlock.spec.ts @@ -66,7 +66,11 @@ tape('BlockBuilder', async (t) => { await blockBuilder.addTransaction(tx) st.fail('should throw error') } catch (error: any) { - if (error.message.includes('tx has a higher gas limit than the remaining gas in the block')) { + if ( + (error.message as string).includes( + 'tx has a higher gas limit than the remaining gas in the block' + ) + ) { st.pass('correct error thrown') } else { st.fail('wrong error thrown') @@ -231,7 +235,7 @@ tape('BlockBuilder', async (t) => { await blockBuilder.revert() st.fail('should throw error') } catch (error: any) { - if (error.message.includes('Block has already been built')) { + if ((error.message as string).includes('Block has already been built')) { st.pass('correct error thrown') } else { st.fail('wrong error thrown') @@ -255,7 +259,7 @@ tape('BlockBuilder', async (t) => { await blockBuilder.revert() st.fail('should throw error') } catch (error: any) { - if (error.message.includes('State has already been reverted')) { + if ((error.message as string).includes('State has already been reverted')) { st.pass('correct error thrown') } else { st.fail('wrong error thrown') @@ -330,7 +334,7 @@ tape('BlockBuilder', async (t) => { st.fail('should throw error') } catch (error: any) { st.ok( - error.message.includes("is less than the block's baseFeePerGas"), + (error.message as string).includes("is less than the block's baseFeePerGas"), 'should fail with appropriate error' ) } diff --git a/packages/vm/tests/api/istanbul/eip-152.spec.ts b/packages/vm/tests/api/istanbul/eip-152.spec.ts index 774d8292a3..7960b96d25 100644 --- a/packages/vm/tests/api/istanbul/eip-152.spec.ts +++ b/packages/vm/tests/api/istanbul/eip-152.spec.ts @@ -80,7 +80,7 @@ const testCases = [ tape('Istanbul: EIP-152', (t) => { t.test('Blake2f', async (st) => { // eslint-disable-next-line no-undef - if ((globalThis).navigator?.userAgent.includes('Firefox')) { + if ((globalThis.navigator?.userAgent as string).includes('Firefox')) { // TODO: investigate why this test hangs in karma with firefox return st.end() } diff --git a/packages/vm/tests/api/istanbul/eip-1884.spec.ts b/packages/vm/tests/api/istanbul/eip-1884.spec.ts index 5c760f3244..e21bdfcaa7 100644 --- a/packages/vm/tests/api/istanbul/eip-1884.spec.ts +++ b/packages/vm/tests/api/istanbul/eip-1884.spec.ts @@ -1,5 +1,5 @@ import * as tape from 'tape' -import { Address, bufferToBigInt } from '@ethereumjs/util' +import { Address, bufferToBigInt, isTruthy } from '@ethereumjs/util' import { Chain, Common, Hardfork } from '@ethereumjs/common' import { VM } from '../../../src/vm' import { createAccount } from '../utils' @@ -26,7 +26,7 @@ tape('Istanbul: EIP-1884', async (t) => { const common = new Common({ chain, hardfork }) const vm = await VM.create({ common }) - const balance = testCase.selfbalance ? BigInt(testCase.selfbalance) : undefined + const balance = isTruthy(testCase.selfbalance) ? BigInt(testCase.selfbalance) : undefined const account = createAccount(BigInt(0), balance) await vm.stateManager.putAccount(addr, account) diff --git a/packages/vm/tests/api/istanbul/eip-2200.spec.ts b/packages/vm/tests/api/istanbul/eip-2200.spec.ts index b369ee25d1..a3b98e6724 100644 --- a/packages/vm/tests/api/istanbul/eip-2200.spec.ts +++ b/packages/vm/tests/api/istanbul/eip-2200.spec.ts @@ -63,13 +63,13 @@ tape('Istanbul: EIP-2200', async (t) => { const runCallArgs = { caller, - gasLimit: testCase.gas ? testCase.gas : BigInt(0xffffffffff), + gasLimit: testCase.gas ?? BigInt(0xffffffffff), to: addr, } try { const res = await vm.evm.runCall(runCallArgs) - if (testCase.err) { + if (typeof testCase.err !== 'undefined') { st.equal(res.execResult.exceptionError?.error, testCase.err) } else { st.equal(res.execResult.exceptionError, undefined) diff --git a/packages/vm/tests/api/runTx.spec.ts b/packages/vm/tests/api/runTx.spec.ts index 8c7d6ec27d..8531c25bca 100644 --- a/packages/vm/tests/api/runTx.spec.ts +++ b/packages/vm/tests/api/runTx.spec.ts @@ -1,5 +1,5 @@ import * as tape from 'tape' -import { Account, Address, MAX_INTEGER } from '@ethereumjs/util' +import { Account, Address, isTruthy, MAX_INTEGER } from '@ethereumjs/util' import { Block } from '@ethereumjs/block' import { Chain, Common, Hardfork } from '@ethereumjs/common' import { @@ -168,9 +168,10 @@ tape('runTx() -> successful API parameter usage', async (t) => { ? tx.maxPriorityFeePerGas : tx.maxFeePerGas - baseFee : tx.gasPrice - baseFee - const expectedCoinbaseBalance = common.isActivatedEIP(1559) - ? result.totalGasSpent * inclusionFeePerGas - : result.amountSpent + const expectedCoinbaseBalance = + common.isActivatedEIP(1559) === true + ? result.totalGasSpent * inclusionFeePerGas + : result.amountSpent t.equals( coinbaseAccount.balance, @@ -660,7 +661,7 @@ tape('runTx() -> skipBalance behavior', async (t) => { const sender = Address.fromPrivateKey(senderKey) for (const balance of [undefined, BigInt(5)]) { - if (balance) { + if (isTruthy(balance)) { await vm.stateManager.modifyAccountFields(sender, { nonce: BigInt(0), balance }) } const tx = Transaction.fromTxData({ diff --git a/packages/vm/tests/api/utils.ts b/packages/vm/tests/api/utils.ts index ffce580da2..5a856cfbc3 100644 --- a/packages/vm/tests/api/utils.ts +++ b/packages/vm/tests/api/utils.ts @@ -104,7 +104,7 @@ export function getTransaction( * Checks if in a karma test runner. * @returns boolean whether running in karma */ -export function isRunningInKarma(): Boolean { +export function isRunningInKarma(): boolean { // eslint-disable-next-line no-undef return typeof (globalThis).window !== 'undefined' && (globalThis).window.__karma__ } diff --git a/packages/vm/tests/tester/config.ts b/packages/vm/tests/tester/config.ts index 6ad2cb8f24..0dabfa4c48 100644 --- a/packages/vm/tests/tester/config.ts +++ b/packages/vm/tests/tester/config.ts @@ -1,5 +1,6 @@ import * as path from 'path' -import { Chain, Common } from '@ethereumjs/common' +import { Chain, Common, Hardfork } from '@ethereumjs/common' +import { isFalsy, isTruthy } from '@ethereumjs/util' /** * Default tests path (git submodule: ethereum-tests) @@ -242,7 +243,7 @@ const testLegacy: any = { export function getTestDirs(network: string, testType: string) { const testDirs = [testType] for (const key in testLegacy) { - if (key.toLowerCase() == network.toLowerCase() && testLegacy[key]) { + if (key.toLowerCase() === network.toLowerCase() && isTruthy(testLegacy[key])) { // Tests for HFs before Istanbul have been moved under `LegacyTests/Constantinople`: // https://github.com/ethereum/tests/releases/tag/v7.0.0-beta.1 testDirs.push('LegacyTests/Constantinople/' + testType) @@ -262,17 +263,16 @@ export function getTestDirs(network: string, testType: string) { * @returns {Common} the Common which should be used */ export function getCommon(targetNetwork: string) { - let network = targetNetwork + let network = targetNetwork.toLowerCase() if (network.includes('+')) { const index = network.indexOf('+') network = network.slice(0, index) } - const networkLowercase = network.toLowerCase() - if (normalHardforks.map((str) => str.toLowerCase()).includes(networkLowercase)) { + if (normalHardforks.map((str) => str.toLowerCase()).includes(network)) { // normal hard fork, return the common with this hard fork // find the right upper/lowercased version const hfName = normalHardforks.reduce((previousValue, currentValue) => - currentValue.toLowerCase() == networkLowercase ? currentValue : previousValue + currentValue.toLowerCase() === network ? currentValue : previousValue ) const mainnetCommon = new Common({ chain: Chain.Mainnet, hardfork: hfName }) const hardforks = mainnetCommon.hardforks() @@ -280,7 +280,7 @@ export function getCommon(targetNetwork: string) { for (const hf of hardforks) { // check if we enable this hf // disable dao hf by default (if enabled at block 0 forces the first 10 blocks to have dao-hard-fork in extraData of block header) - if (mainnetCommon.gteHardfork(hf.name) && hf.name != 'dao') { + if (mainnetCommon.gteHardfork(hf.name) === true && hf.name !== Hardfork.Dao) { // this hardfork should be activated at block 0 testHardforks.push({ name: hf.name, @@ -311,10 +311,10 @@ export function getCommon(targetNetwork: string) { return common } else { // this is not a "default fork" network, but it is a "transition" network. we will test the VM if it transitions the right way - const transitionForks = - transitionNetworks[network] || - transitionNetworks[network.substring(0, 1).toUpperCase() + network.substr(1)] - if (!transitionForks) { + const transitionForks = isTruthy(transitionNetworks[network]) + ? transitionNetworks[network] + : transitionNetworks[network.substring(0, 1).toUpperCase() + network.substr(1)] + if (isFalsy(transitionForks)) { throw new Error('network not supported: ' + network) } const mainnetCommon = new Common({ @@ -324,13 +324,13 @@ export function getCommon(targetNetwork: string) { const hardforks = mainnetCommon.hardforks() const testHardforks = [] for (const hf of hardforks) { - if (mainnetCommon.gteHardfork(hf.name)) { + if (mainnetCommon.gteHardfork(hf.name) === true) { // this hardfork should be activated at block 0 const forkBlockNumber = transitionForks[hf.name] testHardforks.push({ name: hf.name, // forkHash: hf.forkHash, - block: forkBlockNumber === null ? null : forkBlockNumber || 0, // if forkBlockNumber is defined as null, disable it, otherwise use block number or 0 (if its undefined) + block: forkBlockNumber === null || isTruthy(forkBlockNumber) ? forkBlockNumber : 0, // if forkBlockNumber is defined as null, disable it, otherwise use block number or 0 (if its undefined) }) } else { // disable the hardfork @@ -398,11 +398,11 @@ const expectedTestsFull: any = { * Returns the amount of expected tests for a given fork, assuming all tests are ran */ export function getExpectedTests(fork: string, name: string) { - if (expectedTestsFull[name] == undefined) { + if (expectedTestsFull[name] === undefined) { return } for (const key in expectedTestsFull[name]) { - if (fork.toLowerCase() == key.toLowerCase()) { + if (fork.toLowerCase() === key.toLowerCase()) { return expectedTestsFull[name][key] } } diff --git a/packages/vm/tests/tester/index.ts b/packages/vm/tests/tester/index.ts index 4eb51d06ab..4f543d2ff9 100755 --- a/packages/vm/tests/tester/index.ts +++ b/packages/vm/tests/tester/index.ts @@ -15,6 +15,7 @@ import { import { getTestFromSource, getTestsFromArgs } from './testLoader' import { runStateTest } from './runners/GeneralStateTestsRunner' import { runBlockchainTest } from './runners/BlockchainTestsRunner' +import { isFalsy, isTruthy } from '@ethereumjs/util' /** * Test runner @@ -47,10 +48,10 @@ const argv = minimist(process.argv.slice(2)) async function runTests() { let name: string let runner: any - if (argv.state) { + if (isTruthy(argv.state)) { name = 'GeneralStateTests' runner = runStateTest - } else if (argv.blockchain) { + } else if (isTruthy(argv.blockchain)) { name = 'BlockchainTests' runner = runBlockchainTest } else { @@ -58,7 +59,7 @@ async function runTests() { process.exit(1) } - const FORK_CONFIG: string = argv.fork || DEFAULT_FORK_CONFIG + const FORK_CONFIG: string = isTruthy(argv.fork) ? argv.fork : DEFAULT_FORK_CONFIG const FORK_CONFIG_TEST_SUITE = getRequiredForkConfigAlias(FORK_CONFIG) // Examples: Istanbul -> istanbul, MuirGlacier -> muirGlacier @@ -68,7 +69,7 @@ async function runTests() { * Configuration for getting the tests from the ethereum/tests repository */ const testGetterArgs: any = {} - testGetterArgs.skipTests = getSkipTests(argv.skip, argv.runSkipped ? 'NONE' : 'ALL') + testGetterArgs.skipTests = getSkipTests(argv.skip, isTruthy(argv.runSkipped) ? 'NONE' : 'ALL') testGetterArgs.runSkipped = getSkipTests(argv.runSkipped, 'NONE') testGetterArgs.forkConfig = FORK_CONFIG_TEST_SUITE testGetterArgs.file = argv.file @@ -96,7 +97,7 @@ async function runTests() { /** * Modify the forkConfig string to ensure it works with RegEx (escape `+` characters) */ - if (testGetterArgs.forkConfig.includes('+')) { + if ((testGetterArgs.forkConfig as string).includes('+')) { let str = testGetterArgs.forkConfig const indicies = [] for (let i = 0; i < str.length; i++) { @@ -111,12 +112,11 @@ async function runTests() { testGetterArgs.forkConfig = str } - let expectedTests: number | undefined - if (argv['verify-test-amount-alltests']) { - expectedTests = getExpectedTests(FORK_CONFIG_VM, name) - } else if (argv['expected-test-amount']) { - expectedTests = argv['expected-test-amount'] - } + const expectedTests: number | undefined = isTruthy(argv['verify-test-amount-alltests']) + ? getExpectedTests(FORK_CONFIG_VM, name) + : isTruthy(argv['expected-test-amount']) + ? argv['expected-test-amount'] + : undefined /** * Initialization output to console @@ -129,9 +129,9 @@ async function runTests() { return Object.assign( {}, ...Object.entries(args) - .filter(([_k, v]) => v && (v as any).length !== 0) + .filter(([_k, v]) => isTruthy(v) && (v as any).length !== 0) .map(([k, v]) => ({ - [k]: typeof v !== 'string' && (v as any).length ? (v as any).length : v, + [k]: typeof v !== 'string' && isTruthy((v as any).length) ? (v as any).length : v, })) ) } @@ -158,11 +158,11 @@ async function runTests() { console.log(`+${'-'.repeat(width)}+`) console.log() - if (argv.customStateTest) { + if (isTruthy(argv.customStateTest)) { const fileName = argv.customStateTest tape(name, (t) => { getTestFromSource(fileName, async (err: string | undefined, test: any) => { - if (err) { + if (isTruthy(err)) { return t.fail(err) } t.comment(`file: ${fileName} test: ${test.testName}`) @@ -176,8 +176,8 @@ async function runTests() { const failingTests: any = {} ;(t as any).on('result', (o: any) => { - if (o.ok != undefined && !o.ok) { - if (failingTests[testIdentifier]) { + if (typeof o.ok !== 'undefined' && o.ok !== null && isFalsy(o.ok)) { + if (isTruthy(failingTests[testIdentifier])) { failingTests[testIdentifier].push(o.name) } else { failingTests[testIdentifier] = [o.name] @@ -190,7 +190,7 @@ async function runTests() { const dirs = getTestDirs(FORK_CONFIG_VM, name) for (const dir of dirs) { await new Promise((resolve, reject) => { - if (argv.customTestsPath) { + if (isTruthy(argv.customTestsPath)) { testGetterArgs.directory = argv.customTestsPath } else { const testDir = testGetterArgs.dir ?? '' @@ -202,7 +202,7 @@ async function runTests() { async (fileName: string, subDir: string, testName: string, test: any) => { const runSkipped = testGetterArgs.runSkipped const inRunSkipped = runSkipped.includes(fileName) - if (runSkipped.length === 0 || inRunSkipped) { + if (runSkipped.length === 0 || inRunSkipped === true) { testIdentifier = `file: ${subDir} test: ${testName}` t.comment(testIdentifier) await runner(runnerArgs, test, t) diff --git a/packages/vm/tests/tester/runners/BlockchainTestsRunner.ts b/packages/vm/tests/tester/runners/BlockchainTestsRunner.ts index 2d19e0470b..98c20eb272 100644 --- a/packages/vm/tests/tester/runners/BlockchainTestsRunner.ts +++ b/packages/vm/tests/tester/runners/BlockchainTestsRunner.ts @@ -3,7 +3,14 @@ import { Block } from '@ethereumjs/block' import { Blockchain, EthashConsensus } from '@ethereumjs/blockchain' import { Common, ConsensusAlgorithm } from '@ethereumjs/common' import { TransactionFactory } from '@ethereumjs/tx' -import { bufferToBigInt, isHexPrefixed, stripHexPrefix, toBuffer } from '@ethereumjs/util' +import { + bufferToBigInt, + isFalsy, + isHexPrefixed, + isTruthy, + stripHexPrefix, + toBuffer, +} from '@ethereumjs/util' import { RLP } from 'rlp' import { SecureTrie as Trie } from '@ethereumjs/trie' import { setupPreConditions, verifyPostConditions } from '../../util' @@ -37,7 +44,7 @@ export async function runBlockchainTest(options: any, testData: any, t: tape.Tes let validatePow = false // Only run with block validation when sealEngine present in test file // and being set to Ethash PoW validation - if (testData.sealEngine && testData.sealEngine === 'Ethash') { + if (testData.sealEngine === 'Ethash') { if (common.consensusAlgorithm() !== ConsensusAlgorithm.Ethash) { t.skip('SealEngine setting is not matching chain consensus type, skip test.') } @@ -49,7 +56,7 @@ export async function runBlockchainTest(options: any, testData: any, t: tape.Tes const blockData = { header } const genesisBlock = Block.fromBlockData(blockData, { common }) - if (testData.genesisRLP) { + if (isTruthy(testData.genesisRLP)) { const rlp = toBuffer(testData.genesisRLP) t.ok(genesisBlock.serialize().equals(rlp), 'correct genesis RLP') } @@ -67,7 +74,7 @@ export async function runBlockchainTest(options: any, testData: any, t: tape.Tes } let VM - if (options.dist) { + if (options.dist === true) { ;({ VM } = require('../../../dist')) } else { ;({ VM } = require('../../../src')) @@ -101,9 +108,9 @@ export async function runBlockchainTest(options: any, testData: any, t: tape.Tes // Last checked: ethereumjs-testing v1.3.1 (2020-05-11) const paramAll1 = 'expectExceptionALL' const paramAll2 = 'expectException' - const expectException = raw[paramFork] - ? raw[paramFork] - : raw[paramAll1] || raw[paramAll2] || raw.blockHeader == undefined + const expectException = + // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions + raw[paramFork] || raw[paramAll1] || raw[paramAll2] || raw.blockHeader == undefined // Here we decode the rlp to extract the block number // The block library cannot be used, as this throws on certain EIP1559 blocks when trying to convert @@ -122,7 +129,7 @@ export async function runBlockchainTest(options: any, testData: any, t: tape.Tes // transactionSequence is provided when txs are expected to be rejected. // To run this field we try to import them on the current state. - if (raw.transactionSequence) { + if (typeof raw.transactionSequence !== 'undefined') { const parentBlock = await vm.blockchain.getIteratorHead() const blockBuilder = await vm.buildBlock({ parentBlock, @@ -177,13 +184,11 @@ export async function runBlockchainTest(options: any, testData: any, t: tape.Tes // imported if it is not equal to the expected postState. it is useful // for debugging to skip this, so that verifyPostConditions will compare // testData.postState to the actual postState, rather than to the preState. - if (!options.debug) { + if (isFalsy(options.debug)) { // make sure the state is set before checking post conditions const headBlock = await vm.blockchain.getIteratorHead() vm.stateManager._trie.root = headBlock.header.stateRoot - } - - if (options.debug) { + } else { await verifyPostConditions(state, testData.postState, t) } @@ -192,7 +197,7 @@ export async function runBlockchainTest(options: any, testData: any, t: tape.Tes await cacheDB.close() - if (expectException) { + if (isTruthy(expectException)) { t.fail(`expected exception but test did not throw an exception: ${expectException}`) return } diff --git a/packages/vm/tests/tester/runners/GeneralStateTestsRunner.ts b/packages/vm/tests/tester/runners/GeneralStateTestsRunner.ts index 84601e146e..deac3d9e8f 100644 --- a/packages/vm/tests/tester/runners/GeneralStateTestsRunner.ts +++ b/packages/vm/tests/tester/runners/GeneralStateTestsRunner.ts @@ -1,6 +1,6 @@ import * as tape from 'tape' import { SecureTrie as Trie } from '@ethereumjs/trie' -import { toBuffer } from '@ethereumjs/util' +import { isTruthy, toBuffer } from '@ethereumjs/util' import { setupPreConditions, makeTx, makeBlockFromEnv } from '../../util' import { InterpreterStep } from '@ethereumjs/evm/dist//interpreter' @@ -13,7 +13,7 @@ function parseTestCases( ) { let testCases = [] - if (testData['post'][forkConfigTestSuite]) { + if (isTruthy(testData['post'][forkConfigTestSuite])) { testCases = testData['post'][forkConfigTestSuite].map((testCase: any) => { const testIndexes = testCase['indexes'] const tx = { ...testData.transaction } @@ -33,7 +33,7 @@ function parseTestCases( tx.gasLimit = testData.transaction.gasLimit[testIndexes['gas']] tx.value = testData.transaction.value[testIndexes['value']] - if (tx.accessLists) { + if (isTruthy(tx.accessLists)) { tx.accessList = testData.transaction.accessLists[testIndexes['data']] if (tx.chainId == undefined) { tx.chainId = 1 @@ -60,7 +60,7 @@ function parseTestCases( async function runTestCase(options: any, testData: any, t: tape.Test) { let VM - if (options.dist) { + if (isTruthy(options.dist)) { ;({ VM } = require('../../../dist')) } else { ;({ VM } = require('../../../src')) @@ -86,7 +86,7 @@ async function runTestCase(options: any, testData: any, t: tape.Test) { if (tx.validate()) { const block = makeBlockFromEnv(testData.env, { common }) - if (options.jsontrace) { + if (isTruthy(options.jsontrace)) { vm.evm.on('step', function (e: InterpreterStep) { let hexStack = [] hexStack = e.stack.map((item: bigint) => { @@ -148,7 +148,7 @@ export async function runStateTest(options: any, testData: any, t: tape.Test) { return } for (const testCase of testCases) { - if (options.reps) { + if (isTruthy(options.reps)) { let totalTimeSpent = 0 for (let x = 0; x < options.reps; x++) { totalTimeSpent += await runTestCase(options, testCase, t) diff --git a/packages/vm/tests/tester/testLoader.ts b/packages/vm/tests/tester/testLoader.ts index dde77b66ae..513482d4bb 100644 --- a/packages/vm/tests/tester/testLoader.ts +++ b/packages/vm/tests/tester/testLoader.ts @@ -2,6 +2,7 @@ import * as fs from 'fs' import * as path from 'path' import * as dir from 'node-dir' import { DEFAULT_TESTS_PATH } from './config' +import { isTruthy } from '@ethereumjs/util' const falsePredicate = () => false @@ -17,7 +18,7 @@ const falsePredicate = () => false export async function getTests( onFile: Function, fileFilter: RegExp | string[] = /.json$/, - skipPredicate: Function = falsePredicate, + skipPredicate: (...args: any[]) => boolean = falsePredicate, directory: string, excludeDir: RegExp | string[] = [] ): Promise { @@ -134,16 +135,16 @@ export async function getTestsFromArgs(testType: string, onFile: Function, args: return skipTest(name, args.skipVM) } } - if (args.singleSource) { + if (isTruthy(args.singleSource)) { return getTestFromSource(args.singleSource, onFile) } - if (args.file) { + if (isTruthy(args.file)) { fileFilter = new RegExp(args.file) } - if (args.excludeDir) { + if (isTruthy(args.excludeDir)) { excludeDir = new RegExp(args.excludeDir) } - if (args.test) { + if (isTruthy(args.test)) { skipFn = (testName: string) => { return testName !== args.test } diff --git a/packages/vm/tests/util.ts b/packages/vm/tests/util.ts index 8e320e775d..1170dc0d13 100644 --- a/packages/vm/tests/util.ts +++ b/packages/vm/tests/util.ts @@ -15,7 +15,9 @@ import { bigIntToBuffer, bufferToBigInt, bufferToHex, + isFalsy, isHexPrefixed, + isTruthy, setLengthLeft, stripHexPrefix, toBuffer, @@ -107,19 +109,22 @@ export function format(a: any, toZero: boolean = false, isHex: boolean = false): * Make a tx using JSON from tests repo * @param {Object} txData The tx object from tests repo * @param {TxOptions} opts Tx opts that can include an @ethereumjs/common object - * @returns {Transaction} Transaction to be passed to VM.runTx function + * @returns {FeeMarketEIP1559Transaction | AccessListEIP2930Transaction | Transaction} Transaction to be passed to VM.runTx function */ -export function makeTx(txData: any, opts?: TxOptions) { +export function makeTx( + txData: any, + opts?: TxOptions +): FeeMarketEIP1559Transaction | AccessListEIP2930Transaction | Transaction { let tx - if (txData.maxFeePerGas) { + if (isTruthy(txData.maxFeePerGas)) { tx = FeeMarketEIP1559Transaction.fromTxData(txData, opts) - } else if (txData.accessLists) { + } else if (isTruthy(txData.accessLists)) { tx = AccessListEIP2930Transaction.fromTxData(txData, opts) } else { tx = Transaction.fromTxData(txData, opts) } - if (txData.secretKey) { + if (isTruthy(txData.secretKey)) { const privKey = toBuffer(txData.secretKey) return tx.sign(privKey) } @@ -150,7 +155,7 @@ export async function verifyPostConditions(state: any, testData: any, t: tape.Te const address = keyMap[key] delete keyMap[key] - if (testData) { + if (isTruthy(testData)) { const promise = verifyAccountPostConditions(state, address, account, testData, t) queue.push(promise) } else { @@ -216,7 +221,7 @@ export function verifyAccountPostConditions( if (key === '0x') { key = '0x00' - acctData.storage['0x00'] = acctData.storage['0x00'] + acctData.storage['0x00'] = isTruthy(acctData.storage['0x00']) ? acctData.storage['0x00'] : acctData.storage['0x'] delete acctData.storage['0x'] @@ -252,9 +257,9 @@ export function verifyAccountPostConditions( */ export function verifyGas(results: any, testData: any, t: tape.Test) { const coinbaseAddr = testData.env.currentCoinbase - const preBal = testData.pre[coinbaseAddr] ? testData.pre[coinbaseAddr].balance : 0 + const preBal = isTruthy(testData.pre[coinbaseAddr]) ? testData.pre[coinbaseAddr].balance : 0 - if (!testData.post[coinbaseAddr]) { + if (isFalsy(testData.post[coinbaseAddr])) { return } @@ -274,7 +279,7 @@ export function verifyGas(results: any, testData: any, t: tape.Test) { * @param testData from tests repo */ export function verifyLogs(logs: any, testData: any, t: tape.Test) { - if (testData.logs) { + if (isTruthy(testData.logs)) { testData.logs.forEach(function (log: any, i: number) { const rlog = logs[i] t.equal(rlog[0].toString('hex'), log.address, 'log: valid address') @@ -313,8 +318,7 @@ export function makeBlockHeader(data: any, opts?: BlockOptions) { /** * makeBlockFromEnv - helper to create a block from the env object in tests repo * @param env object from tests repo - * @param transactions transactions for the block (optional) - * @param uncleHeaders uncle headers for the block (optional) + * @param opts block options (optional) * @returns the block */ export function makeBlockFromEnv(env: any, opts?: BlockOptions): Block { @@ -353,7 +357,7 @@ export async function setupPreConditions(state: VmState, testData: any) { const stateRoot = (await state.getAccount(address)).stateRoot - if (testData.exec && testData.exec.address === addressStr) { + if (testData.exec?.address === addressStr) { testData.root = stateRoot } @@ -388,7 +392,7 @@ export function getRequiredForkConfigAlias(forkConfig: string): string { * Checks if in a karma test runner. * @returns boolean whether running in karma */ -export function isRunningInKarma(): Boolean { +export function isRunningInKarma(): boolean { // eslint-disable-next-line no-undef return typeof (globalThis).window !== 'undefined' && (globalThis).window.__karma__ }