Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

block: remove isTruthy and isFalsy #2256

Merged
merged 8 commits into from
Aug 31, 2022
6 changes: 3 additions & 3 deletions packages/block/src/block.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { ConsensusType } from '@ethereumjs/common'
import { RLP } from '@ethereumjs/rlp'
import { Trie } from '@ethereumjs/trie'
import { Capability, TransactionFactory } from '@ethereumjs/tx'
import { KECCAK256_RLP, arrToBufArr, bufArrToArr, bufferToHex, isTruthy } from '@ethereumjs/util'
import { KECCAK256_RLP, arrToBufArr, bufArrToArr, bufferToHex } from '@ethereumjs/util'
import { keccak256 } from 'ethereum-cryptography/keccak'

import { BlockHeader } from './header'
Expand Down Expand Up @@ -104,7 +104,7 @@ export class Block {

// parse transactions
const transactions = []
for (const txData of isTruthy(txsData) ? txsData : []) {
for (const txData of txsData ?? []) {
transactions.push(
TransactionFactory.fromBlockBodyData(txData, {
...opts,
Expand All @@ -130,7 +130,7 @@ export class Block {
if (opts?.hardforkByTTD !== undefined) {
uncleOpts.hardforkByBlockNumber = true
}
for (const uncleHeaderData of isTruthy(uhsData) ? uhsData : []) {
for (const uncleHeaderData of uhsData ?? []) {
uncleHeaders.push(BlockHeader.fromValuesArray(uncleHeaderData, uncleOpts))
}

Expand Down
27 changes: 16 additions & 11 deletions packages/block/src/from-rpc.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { TransactionFactory } from '@ethereumjs/tx'
import { isTruthy, setLengthLeft, toBuffer } from '@ethereumjs/util'
import { setLengthLeft, toBuffer } from '@ethereumjs/util'

import { blockHeaderFromRpc } from './header-from-rpc'
import { numberToHex } from './helpers'

import { Block } from './index'

import type { BlockOptions } from './index'
import type { BlockOptions, JsonRpcBlock } from './index'
import type { TxData, TypedTransaction } from '@ethereumjs/tx'

function normalizeTxParams(_txParams: any) {
Expand All @@ -20,7 +20,10 @@ function normalizeTxParams(_txParams: any) {
txParams.value = numberToHex(txParams.value)

// strict byte length checking
txParams.to = isTruthy(txParams.to) ? setLengthLeft(toBuffer(txParams.to), 20) : null
txParams.to =
txParams.to !== null && txParams.to !== undefined
? 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}.
Expand All @@ -38,17 +41,19 @@ function normalizeTxParams(_txParams: any) {
* @param uncles - Optional list of Ethereum JSON RPC of uncles (eth_getUncleByBlockHashAndIndex)
* @param options - An object describing the blockchain
*/
export function blockFromRpc(blockParams: any, uncles: any[] = [], options?: BlockOptions) {
export function blockFromRpc(
blockParams: JsonRpcBlock,
uncles: any[] = [],
options?: BlockOptions
) {
const header = blockHeaderFromRpc(blockParams, options)

const transactions: TypedTransaction[] = []
if (isTruthy(blockParams.transactions)) {
const opts = { common: header._common }
for (const _txParams of blockParams.transactions) {
const txParams = normalizeTxParams(_txParams)
const tx = TransactionFactory.fromTxData(txParams as TxData, opts)
transactions.push(tx)
}
const opts = { common: header._common }
for (const _txParams of blockParams.transactions) {
const txParams = normalizeTxParams(_txParams)
const tx = TransactionFactory.fromTxData(txParams as TxData, opts)
transactions.push(tx)
}

const uncleHeaders = uncles.map((uh) => blockHeaderFromRpc(uh, options))
Expand Down
7 changes: 5 additions & 2 deletions packages/block/src/header-from-rpc.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
import { BlockHeader } from './header'
import { numberToHex } from './helpers'

import type { BlockOptions } from './types'
import type { BlockOptions, JsonRpcBlock } from './types'

/**
* Creates a new block header object from Ethereum JSON RPC.
*
* @param blockParams - Ethereum JSON RPC of block (eth_getBlockByNumber)
* @param options - An object describing the blockchain
*/
export function blockHeaderFromRpc(blockParams: any, options?: BlockOptions) {
export function blockHeaderFromRpc(
blockParams: Omit<JsonRpcBlock, 'receiptsRoot'> & { receiptRoot?: string; receiptsRoot?: string },
acolytec3 marked this conversation as resolved.
Show resolved Hide resolved
options?: BlockOptions
) {
const {
parentHash,
sha3Uncles,
Expand Down
24 changes: 15 additions & 9 deletions packages/block/src/header.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ import {
bufferToHex,
ecrecover,
ecsign,
isFalsy,
isTruthy,
toType,
zeros,
} from '@ethereumjs/util'
Expand Down Expand Up @@ -160,9 +158,9 @@ export class BlockHeader {

const parentHash = toType(headerData.parentHash, TypeOutput.Buffer) ?? defaults.parentHash
const uncleHash = toType(headerData.uncleHash, TypeOutput.Buffer) ?? defaults.uncleHash
const coinbase = isTruthy(headerData.coinbase)
? new Address(toType(headerData.coinbase, TypeOutput.Buffer))
: defaults.coinbase
const coinbase = new Address(
toType(headerData.coinbase ?? defaults.coinbase, TypeOutput.Buffer)
)
const stateRoot = toType(headerData.stateRoot, TypeOutput.Buffer) ?? defaults.stateRoot
const transactionsTrie =
toType(headerData.transactionsTrie, TypeOutput.Buffer) ?? defaults.transactionsTrie
Expand Down Expand Up @@ -300,9 +298,13 @@ export class BlockHeader {
throw new Error(msg)
}
const londonHfBlock = this._common.hardforkBlock(Hardfork.London)
if (isTruthy(londonHfBlock) && this.number === londonHfBlock) {
if (
typeof londonHfBlock === 'bigint' &&
londonHfBlock !== BigInt(0) &&
this.number === londonHfBlock
) {
const initialBaseFee = this._common.param('gasConfig', 'initialBaseFee')
if (this.baseFeePerGas! !== initialBaseFee) {
if (this.baseFeePerGas !== initialBaseFee) {
const msg = this._errorMsg('Initial EIP1559 block does not have initial base fee')
throw new Error(msg)
}
Expand Down Expand Up @@ -404,7 +406,11 @@ 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 (isTruthy(londonHardforkBlock) && this.number === londonHardforkBlock) {
if (
typeof londonHardforkBlock === 'bigint' &&
londonHardforkBlock !== BigInt(0) &&
this.number === londonHardforkBlock
) {
const elasticity = this._common.param('gasConfig', 'elasticityMultiplier')
parentGasLimit = parentGasLimit * elasticity
}
Expand Down Expand Up @@ -774,7 +780,7 @@ export class BlockHeader {
return
}
const DAOActivationBlock = this._common.hardforkBlock(Hardfork.Dao)
if (isFalsy(DAOActivationBlock) || this.number < DAOActivationBlock) {
if (DAOActivationBlock === null || this.number < DAOActivationBlock) {
return
}
const DAO_ExtraData = Buffer.from('64616f2d686172642d666f726b', 'hex')
Expand Down
4 changes: 2 additions & 2 deletions packages/block/src/helpers.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { TypeOutput, isFalsy, isHexString, toType } from '@ethereumjs/util'
import { TypeOutput, isHexString, toType } from '@ethereumjs/util'

import type { BlockHeaderBuffer, HeaderData } from './types'

Expand All @@ -7,7 +7,7 @@ import type { BlockHeaderBuffer, HeaderData } from './types'
* @param {string} input string to check, convert, and return
*/
export const numberToHex = function (input?: string) {
if (isFalsy(input)) return undefined
if (input === undefined) return undefined
if (!isHexString(input)) {
const regex = new RegExp(/^\d+$/) // test to make sure input contains only digits
if (!regex.test(input)) {
Expand Down
29 changes: 29 additions & 0 deletions packages/block/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import type { Common } from '@ethereumjs/common'
import type {
AccessListEIP2930TxData,
FeeMarketEIP1559TxData,
JsonRpcTx,
JsonTx,
TxData,
} from '@ethereumjs/tx'
Expand Down Expand Up @@ -150,3 +151,31 @@ export interface JsonHeader {
nonce?: string
baseFeePerGas?: string
}

/*
* Based on https://eth.wiki/json-rpc/API
*/
export interface JsonRpcBlock {
number: string // the block number. null when pending block.
hash: string // hash of the block. null when pending block.
parentHash: string // hash of the parent block.
mixHash?: string // bit hash which proves combined with the nonce that a sufficient amount of computation has been carried out on this block.
nonce: string // hash of the generated proof-of-work. null when pending block.
sha3Uncles: string // SHA3 of the uncles data in the block.
logsBloom: string // the bloom filter for the logs of the block. null when pending block.
transactionsRoot: string // the root of the transaction trie of the block.
stateRoot: string // the root of the final state trie of the block.
receiptRoot?: string // the root of the receipts trie of the block.
receiptsRoot: string // the root of the receipts trie of the block.
miner: string // the address of the beneficiary to whom the mining rewards were given.
difficulty: string // integer of the difficulty for this block.
totalDifficulty: string // integer of the total difficulty of the chain until this block.
extraData: string // the “extra data” field of this block.
size: string // integer the size of this block in bytes.
gasLimit: string // the maximum gas allowed in this block.
gasUsed: string // the total used gas by all transactions in this block.
timestamp: string // the unix timestamp for when the block was collated.
transactions: Array<JsonRpcTx | string> // Array of transaction objects, or 32 Bytes transaction hashes depending on the last given parameter.
uncles: string[] // Array of uncle hashes
baseFeePerGas?: string // If EIP-1559 is enabled for this block, returns the base fee per gas
}
4 changes: 2 additions & 2 deletions packages/block/test/block.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import * as testDataPreLondon2 from './testdata/testdata_pre-london-2.json'
import * as testDataPreLondon from './testdata/testdata_pre-london.json'
import * as testnetMerge from './testdata/testnetMerge.json'

import type { BlockBuffer } from '../src'
import type { BlockBuffer, JsonRpcBlock } from '../src'
import type { NestedUint8Array } from '@ethereumjs/util'

tape('[Block]: block functions', function (t) {
Expand Down Expand Up @@ -176,7 +176,7 @@ tape('[Block]: block functions', function (t) {
const common = new Common({ chain: Chain.Goerli, hardfork: Hardfork.Chainstart })

try {
blockFromRpc(testDataFromRpcGoerli, [], { common })
blockFromRpc(testDataFromRpcGoerli as JsonRpcBlock, [], { common })
st.pass('does not throw')
} catch (error: any) {
st.fail('error thrown')
Expand Down
19 changes: 12 additions & 7 deletions packages/block/test/from-rpc.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,21 @@ import * as blockDataWithUncles from './testdata/testdata-from-rpc-with-uncles.j
import * as uncleBlockData from './testdata/testdata-from-rpc-with-uncles_uncle-block-data.json'
import * as blockData from './testdata/testdata-from-rpc.json'

import type { JsonRpcBlock } from '../src/types'
import type { Transaction } from '@ethereumjs/tx'

tape('[fromRPC]: block #2924874', function (t) {
const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Istanbul })

t.test('should create a block with transactions with valid signatures', function (st) {
const block = blockFromRpc(blockData, [], { common })
const block = blockFromRpc(blockData as JsonRpcBlock, [], { common })
const allValid = block.transactions.every((tx) => tx.verifySignature())
st.equal(allValid, true, 'all transaction signatures are valid')
st.end()
})

t.test('should create a block header with the correct hash', function (st) {
const block = blockHeaderFromRpc(blockData, { common })
const block = blockHeaderFromRpc(blockData as JsonRpcBlock, { common })
const hash = Buffer.from(blockData.hash.slice(2), 'hex')
st.ok(block.hash().equals(hash))
st.end()
Expand All @@ -45,7 +46,7 @@ tape('[fromRPC]:', function (t) {
const blockDataTransactionValueAsInteger = blockData
blockDataTransactionValueAsInteger.transactions[0].value = valueAsIntegerString
const blockFromTransactionValueAsInteger = blockFromRpc(
blockDataTransactionValueAsInteger,
blockDataTransactionValueAsInteger as JsonRpcBlock,
undefined,
{ common }
)
Expand All @@ -66,7 +67,7 @@ tape('[fromRPC]:', function (t) {
const blockDataTransactionGasPriceAsInteger = blockData
blockDataTransactionGasPriceAsInteger.transactions[0].gasPrice = gasPriceAsIntegerString
const blockFromTransactionGasPriceAsInteger = blockFromRpc(
blockDataTransactionGasPriceAsInteger,
blockDataTransactionGasPriceAsInteger as JsonRpcBlock,
undefined,
{ common }
)
Expand All @@ -83,9 +84,13 @@ tape('[fromRPC]:', function (t) {
'should create a block given json data that includes a difficulty parameter of type integer string',
function (st) {
const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.London })
const blockDifficultyAsInteger = blockFromRpc(blockDataDifficultyAsInteger, undefined, {
common,
})
const blockDifficultyAsInteger = blockFromRpc(
blockDataDifficultyAsInteger as JsonRpcBlock,
undefined,
{
common,
}
)
st.equal(
blockDifficultyAsInteger.header.difficulty.toString(),
blockDataDifficultyAsInteger.difficulty
Expand Down
4 changes: 2 additions & 2 deletions packages/block/test/util.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Chain, Common, Hardfork } from '@ethereumjs/common'
import { RLP } from '@ethereumjs/rlp'
import { bufArrToArr, isTruthy } from '@ethereumjs/util'
import { bufArrToArr } from '@ethereumjs/util'
import { keccak256 } from 'ethereum-cryptography/keccak'

import { Block } from '../src'
Expand Down Expand Up @@ -33,7 +33,7 @@ function createBlock(

const londonHfBlock = common.hardforkBlock(Hardfork.London)
const baseFeePerGas =
isTruthy(londonHfBlock) && number > londonHfBlock
typeof londonHfBlock === 'bigint' && londonHfBlock !== BigInt(0) && number > londonHfBlock
? parentBlock.header.calcNextBaseFee()
: undefined

Expand Down