Skip to content

Commit

Permalink
util: refactor bigint to address helper into Address.fromBigInt method (
Browse files Browse the repository at this point in the history
#3544)

* util: refactor bigint to address helper into fromBigInt constructor

* evm: refactor using fromBigInt method

* refactor: address constructor usage

* evm: wrapper helper for evm stack bigint addresses

* Update packages/evm/src/opcodes/util.ts

Co-authored-by: Jochem Brouwer <jochembrouwer96@gmail.com>

* util: remove redundant conversion

* address: add test vectors for big int constructor

---------

Co-authored-by: Jochem Brouwer <jochembrouwer96@gmail.com>
  • Loading branch information
gabrocheleau and jochem-brouwer committed Jul 26, 2024
1 parent 8d87e80 commit 8441f9c
Show file tree
Hide file tree
Showing 101 changed files with 707 additions and 497 deletions.
4 changes: 2 additions & 2 deletions packages/block/examples/4844.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { createBlockFromBlockData } from '@ethereumjs/block'
import { Chain, Common, Hardfork } from '@ethereumjs/common'
import { create4844BlobTx } from '@ethereumjs/tx'
import { Address } from '@ethereumjs/util'
import { createAddressFromPrivateKey } from '@ethereumjs/util'
import { randomBytes } from 'crypto'
import { loadKZG } from 'kzg-wasm'

Expand All @@ -16,7 +16,7 @@ const main = async () => {
},
})
const blobTx = create4844BlobTx(
{ blobsData: ['myFirstBlob'], to: Address.fromPrivateKey(randomBytes(32)) },
{ blobsData: ['myFirstBlob'], to: createAddressFromPrivateKey(randomBytes(32)) },
{ common },
)

Expand Down
8 changes: 5 additions & 3 deletions packages/block/src/header.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ import {
bytesToHex,
bytesToUtf8,
concatBytes,
createAddressFromPublicKey,
createZeroAddress,
ecrecover,
ecsign,
equalsBytes,
Expand Down Expand Up @@ -177,7 +179,7 @@ export class BlockHeader {
const defaults = {
parentHash: zeros(32),
uncleHash: KECCAK256_RLP_ARRAY,
coinbase: Address.zero(),
coinbase: createZeroAddress(),
stateRoot: zeros(32),
transactionsTrie: KECCAK256_RLP,
receiptTrie: KECCAK256_RLP,
Expand Down Expand Up @@ -932,13 +934,13 @@ export class BlockHeader {
const extraSeal = this.cliqueExtraSeal()
// Reasonable default for default blocks
if (extraSeal.length === 0 || equalsBytes(extraSeal, new Uint8Array(65))) {
return Address.zero()
return createZeroAddress()
}
const r = extraSeal.subarray(0, 32)
const s = extraSeal.subarray(32, 64)
const v = bytesToBigInt(extraSeal.subarray(64, 65)) + BIGINT_27
const pubKey = ecrecover(this.cliqueSigHash(), v, r, s)
return Address.fromPublicKey(pubKey)
return createAddressFromPublicKey(pubKey)
}

/**
Expand Down
10 changes: 7 additions & 3 deletions packages/block/test/clique.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Chain, Common, Hardfork } from '@ethereumjs/common'
import { Address, hexToBytes } from '@ethereumjs/util'
import { Address, createZeroAddress, hexToBytes } from '@ethereumjs/util'
import { assert, describe, it } from 'vitest'

import { BlockHeader } from '../src/header.js'
Expand Down Expand Up @@ -68,7 +68,11 @@ describe('[Header]: Clique PoA Functionality', () => {
)
const msg =
'cliqueEpochTransitionSigners() -> should return the correct epoch transition signer list on epoch block'
assert.deepEqual(header.cliqueEpochTransitionSigners(), [Address.zero(), Address.zero()], msg)
assert.deepEqual(
header.cliqueEpochTransitionSigners(),
[createZeroAddress(), createZeroAddress()],
msg,
)
})

type Signer = {
Expand Down Expand Up @@ -99,7 +103,7 @@ describe('[Header]: Clique PoA Functionality', () => {

header = BlockHeader.fromHeaderData({ extraData: new Uint8Array(97) }, { common })
assert.ok(
header.cliqueSigner().equals(Address.zero()),
header.cliqueSigner().equals(createZeroAddress()),
'should return zero address on default block',
)
})
Expand Down
10 changes: 5 additions & 5 deletions packages/block/test/header.spec.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { Chain, Common, Hardfork } from '@ethereumjs/common'
import { RLP } from '@ethereumjs/rlp'
import {
Address,
KECCAK256_RLP,
KECCAK256_RLP_ARRAY,
bytesToHex,
concatBytes,
createZeroAddress,
equalsBytes,
hexToBytes,
zeros,
Expand All @@ -28,7 +28,7 @@ describe('[Block]: Header functions', () => {
function compareDefaultHeader(header: BlockHeader) {
assert.ok(equalsBytes(header.parentHash, zeros(32)))
assert.ok(equalsBytes(header.uncleHash, KECCAK256_RLP_ARRAY))
assert.ok(header.coinbase.equals(Address.zero()))
assert.ok(header.coinbase.equals(createZeroAddress()))
assert.ok(equalsBytes(header.stateRoot, zeros(32)))
assert.ok(equalsBytes(header.transactionsTrie, KECCAK256_RLP))
assert.ok(equalsBytes(header.receiptTrie, KECCAK256_RLP))
Expand Down Expand Up @@ -380,7 +380,7 @@ describe('[Block]: Header functions', () => {
testCase = 'should throw on non-zero beneficiary (coinbase) for epoch transition block'
headerData.number = common.consensusConfig().epoch
headerData.coinbase = Address.fromString('0x091dcd914fCEB1d47423e532955d1E62d1b2dAEf')
headerData.coinbase = createAddressFromString('0x091dcd914fCEB1d47423e532955d1E62d1b2dAEf')
header = BlockHeader.fromHeaderData(headerData, { common })
try {
await header.validate(blockchain)
Expand All @@ -393,7 +393,7 @@ describe('[Block]: Header functions', () => {
}
}
headerData.number = 1
headerData.coinbase = Address.zero()
headerData.coinbase = createZeroAddress()
testCase = 'should throw on non-zero mixHash'
headerData.mixHash = new Uint8Array(32).fill(1)
Expand Down Expand Up @@ -455,7 +455,7 @@ describe('[Block]: Header functions', () => {
*/
it('should test validateGasLimit()', () => {
const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.London })
const bcBlockGasLimitTestData = testData.tests.BlockGasLimit2p63m1
const bcBlockGasLimitTestData = testData.default.tests.BlockGasLimit2p63m1

for (const key of Object.keys(bcBlockGasLimitTestData)) {
const genesisRlp = hexToBytes(
Expand Down
4 changes: 2 additions & 2 deletions packages/block/test/mergeBlock.spec.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { Chain, Common, Hardfork } from '@ethereumjs/common'
import {
Address,
KECCAK256_RLP,
KECCAK256_RLP_ARRAY,
createZeroAddress,
equalsBytes,
hexToBytes,
zeros,
Expand All @@ -21,7 +21,7 @@ const common = new Common({
function validateMergeHeader(header: BlockHeader) {
assert.ok(equalsBytes(header.parentHash, zeros(32)), 'parentHash')
assert.ok(equalsBytes(header.uncleHash, KECCAK256_RLP_ARRAY), 'uncleHash')
assert.ok(header.coinbase.equals(Address.zero()), 'coinbase')
assert.ok(header.coinbase.equals(createZeroAddress()), 'coinbase')
assert.ok(equalsBytes(header.stateRoot, zeros(32)), 'stateRoot')
assert.ok(equalsBytes(header.transactionsTrie, KECCAK256_RLP), 'transactionsTrie')
assert.ok(equalsBytes(header.receiptTrie, KECCAK256_RLP), 'receiptTrie')
Expand Down
12 changes: 9 additions & 3 deletions packages/blockchain/test/clique.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,13 @@ import {
Hardfork,
createCustomCommon,
} from '@ethereumjs/common'
import { Address, concatBytes, hexToBytes } from '@ethereumjs/util'
import {
Address,
concatBytes,
createAddressFromString,
createZeroAddress,
hexToBytes,
} from '@ethereumjs/util'
import { assert, describe, it } from 'vitest'

import { CLIQUE_NONCE_AUTH, CLIQUE_NONCE_DROP, CliqueConsensus } from '../src/consensus/clique.js'
Expand Down Expand Up @@ -114,7 +120,7 @@ function getBlock(
common = common ?? COMMON
const number = lastBlock.header.number + BigInt(1)

let coinbase = Address.zero()
let coinbase = createZeroAddress()
let nonce = CLIQUE_NONCE_DROP
let extraData = EXTRA_DATA
if (beneficiary) {
Expand Down Expand Up @@ -214,7 +220,7 @@ describe('Clique: Initialization', () => {
// _validateConsensus needs to be true to trigger this test condition
;(blockchain as any)._validateConsensus = true
const number = (COMMON.consensusConfig() as CliqueConfig).epoch
const unauthorizedSigner = Address.fromString('0x00a839de7922491683f547a67795204763ff8237')
const unauthorizedSigner = createAddressFromString('0x00a839de7922491683f547a67795204763ff8237')
const extraData = concatBytes(
new Uint8Array(32),
A.address.toBytes(),
Expand Down
15 changes: 8 additions & 7 deletions packages/client/bin/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,12 @@ import {
} from '@ethereumjs/common'
import { RLP } from '@ethereumjs/rlp'
import {
Address,
BIGINT_2,
bytesToHex,
calculateSigRecovery,
concatBytes,
createAddressFromPrivateKey,
createAddressFromString,
ecrecover,
ecsign,
hexToBytes,
Expand Down Expand Up @@ -65,7 +66,7 @@ import type { RPCArgs } from './startRpc.js'
import type { Block, BlockBytes } from '@ethereumjs/block'
import type { ConsensusDict } from '@ethereumjs/blockchain'
import type { CustomCrypto } from '@ethereumjs/common'
import type { GenesisState, PrefixedHexString } from '@ethereumjs/util'
import type { Address, GenesisState, PrefixedHexString } from '@ethereumjs/util'
import type { AbstractLevel } from 'abstract-level'
import type { Server as RPCServer } from 'jayson/promise/index.js'

Expand Down Expand Up @@ -371,7 +372,7 @@ const args: ClientOpts = yargs
describe:
'Address for mining rewards (etherbase). If not provided, defaults to the primary account',
string: true,
coerce: (coinbase) => Address.fromString(coinbase),
coerce: (coinbase) => createAddressFromString(coinbase),
})
.option('saveReceipts', {
describe:
Expand Down Expand Up @@ -835,13 +836,13 @@ async function inputAccounts() {
const isFile = existsSync(path.resolve(addresses[0]))
if (!isFile) {
for (const addressString of addresses) {
const address = Address.fromString(addressString)
const address = createAddressFromString(addressString)
const inputKey = (await question(
`Please enter the 0x-prefixed private key to unlock ${address}:\n`,
)) as PrefixedHexString
;(rl as any).history = (rl as any).history.slice(1)
const privKey = hexToBytes(inputKey)
const derivedAddress = Address.fromPrivateKey(privKey)
const derivedAddress = createAddressFromPrivateKey(privKey)
if (address.equals(derivedAddress)) {
accounts.push([address, privKey])
} else {
Expand All @@ -854,7 +855,7 @@ async function inputAccounts() {
} else {
const acc = readFileSync(path.resolve(args.unlock!), 'utf-8').replace(/(\r\n|\n|\r)/gm, '')
const privKey = hexToBytes(`0x${acc}`) // See docs: acc has to be non-zero prefixed in the file
const derivedAddress = Address.fromPrivateKey(privKey)
const derivedAddress = createAddressFromPrivateKey(privKey)
accounts.push([derivedAddress, privKey])
}
} catch (e: any) {
Expand All @@ -870,7 +871,7 @@ async function inputAccounts() {
*/
function generateAccount(): Account {
const privKey = randomBytes(32)
const address = Address.fromPrivateKey(privKey)
const address = createAddressFromPrivateKey(privKey)
console.log('='.repeat(50))
console.log('Account generated for mining blocks:')
console.log(`Address: ${address}`)
Expand Down
14 changes: 7 additions & 7 deletions packages/client/devnets/4844-interop/tools/txGenerator.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
// Adapted from - https://github.com/Inphi/eip4844-interop/blob/master/blob_tx_generator/blob.js
import { Common, Hardfork } from '@ethereumjs/common'
import { BlobEIP4844Transaction, TransactionType, TxData } from '@ethereumjs/tx'
import { createCommonFromGethGenesis, Hardfork } from '@ethereumjs/common'
import { createTxFromTxData, TransactionType, TxData } from '@ethereumjs/tx'
import {
Address,
blobsToCommitments,
commitmentsToVersionedHashes,
getBlobs,
bytesToHex,
hexToBytes,
createAddressFromPrivateKey,
} from '@ethereumjs/util'

import { randomBytes } from '@ethereumjs/util'
Expand All @@ -18,8 +18,8 @@ import { loadKZG } from 'kzg-wasm'
const clientPort = parseInt(process.argv[2]) // EL client port number
const input = process.argv[3] // text to generate blob from
const genesisJson = require(process.argv[4]) // Genesis parameters
const pkey = hexToBytes('0x' + process.argv[5]) // private key of tx sender as unprefixed hex string (unprefixed in args)
const sender = Address.fromPrivateKey(pkey)
const pkey = hexToBytes(`0x${process.argv[5]}`) // private key of tx sender as unprefixed hex string (unprefixed in args)
const sender = createAddressFromPrivateKey(pkey)

async function getNonce(client: Client, account: string) {
const nonce = await client.request('eth_getTransactionCount', [account, 'latest'], 2.0)
Expand All @@ -41,7 +41,7 @@ async function run(data: any) {
const commitments = blobsToCommitments(kzg, blobs)
const hashes = commitmentsToVersionedHashes(commitments)

const account = Address.fromPrivateKey(randomBytes(32))
const account = createAddressFromPrivateKey(randomBytes(32))
const txData: TxData[TransactionType.BlobEIP4844] = {
to: account.toString(),
data: '0x',
Expand All @@ -62,7 +62,7 @@ async function run(data: any) {
txData.gasLimit = BigInt(28000000)
const nonce = await getNonce(client, sender.toString())
txData.nonce = BigInt(nonce)
const blobTx = BlobEIP4844Transaction.fromTxData(txData, { common }).sign(pkey)
const blobTx = createTxFromTxData<TransactionType.BlobEIP4844>(txData, { common }).sign(pkey)

const serializedWrapper = blobTx.serializeNetworkWrapper()

Expand Down
4 changes: 2 additions & 2 deletions packages/client/src/miner/pendingBlock.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { Hardfork } from '@ethereumjs/common'
import { BlobEIP4844Transaction } from '@ethereumjs/tx'
import {
Address,
BIGINT_1,
BIGINT_2,
TypeOutput,
bigIntToUnpaddedBytes,
bytesToHex,
concatBytes,
createZeroAddress,
equalsBytes,
toBytes,
toType,
Expand Down Expand Up @@ -140,7 +140,7 @@ export class PendingBlock {
const validatorIndex = bigIntToUnpaddedBytes(
toType(withdrawal.validatorIndex ?? 0, TypeOutput.BigInt),
)
const address = toType(withdrawal.address ?? Address.zero(), TypeOutput.Uint8Array)
const address = toType(withdrawal.address ?? createZeroAddress(), TypeOutput.Uint8Array)
const amount = bigIntToUnpaddedBytes(toType(withdrawal.amount ?? 0, TypeOutput.BigInt))
withdrawalsBufTemp.push(concatBytes(indexBuf, validatorIndex, address, amount))
}
Expand Down
15 changes: 11 additions & 4 deletions packages/client/src/rpc/modules/debug.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
import { Address, TypeOutput, bigIntToHex, bytesToHex, hexToBytes, toType } from '@ethereumjs/util'
import {
TypeOutput,
bigIntToHex,
bytesToHex,
createAddressFromString,
hexToBytes,
toType,
} from '@ethereumjs/util'
import { type VM, encodeReceipt, runTx } from '@ethereumjs/vm'

import { INTERNAL_ERROR, INVALID_PARAMS } from '../error-code.js'
Expand Down Expand Up @@ -304,8 +311,8 @@ export class Debug {
next?.()
})
const runCallOpts = {
caller: from !== undefined ? Address.fromString(from) : undefined,
to: to !== undefined ? Address.fromString(to) : undefined,
caller: from !== undefined ? createAddressFromString(from) : undefined,
to: to !== undefined ? createAddressFromString(to) : undefined,
gasLimit: toType(gasLimit, TypeOutput.BigInt),
gasPrice: toType(gasPrice, TypeOutput.BigInt),
value: toType(value, TypeOutput.BigInt),
Expand Down Expand Up @@ -373,7 +380,7 @@ export class Debug {
// await here so that any error can be handled in the catch below for proper response
return vmCopy.stateManager.dumpStorageRange!(
// Validator already verified that `account` and `startKey` are properly formatted.
Address.fromString(account),
createAddressFromString(account),
BigInt(startKey),
limit,
)
Expand Down
Loading

0 comments on commit 8441f9c

Please sign in to comment.