Skip to content

Commit

Permalink
Merge branch 'master' into vm/verkle-testing
Browse files Browse the repository at this point in the history
  • Loading branch information
gabrocheleau authored Nov 11, 2024
2 parents 760b3f8 + 41f158b commit 5ccea5f
Show file tree
Hide file tree
Showing 20 changed files with 984 additions and 723 deletions.
143 changes: 115 additions & 28 deletions packages/tx/src/1559/tx.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { Common } from '@ethereumjs/common'
import {
BIGINT_0,
BIGINT_27,
Expand All @@ -9,14 +8,13 @@ import {
toBytes,
} from '@ethereumjs/util'

import { BaseTransaction } from '../baseTransaction.js'
import * as EIP1559 from '../capabilities/eip1559.js'
import * as EIP2718 from '../capabilities/eip2718.js'
import * as EIP2930 from '../capabilities/eip2930.js'
import * as Legacy from '../capabilities/legacy.js'
import { paramsTx } from '../params.js'
import { getBaseJSON, sharedConstructor, valueBoundaryCheck } from '../features/util.js'
import { TransactionType } from '../types.js'
import { AccessLists, validateNotArray } from '../util.js'
import { AccessLists } from '../util.js'

import { createFeeMarket1559Tx } from './constructors.js'

Expand All @@ -25,9 +23,14 @@ import type {
AccessListBytes,
TxData as AllTypesTxData,
TxValuesArray as AllTypesTxValuesArray,
Capability,
JSONTx,
TransactionCache,
TransactionInterface,
TxOptions,
} from '../types.js'
import type { Common } from '@ethereumjs/common'
import type { Address } from '@ethereumjs/util'

export type TxData = AllTypesTxData[TransactionType.FeeMarketEIP1559]
export type TxValuesArray = AllTypesTxValuesArray[TransactionType.FeeMarketEIP1559]
Expand All @@ -38,15 +41,42 @@ export type TxValuesArray = AllTypesTxValuesArray[TransactionType.FeeMarketEIP15
* - TransactionType: 2
* - EIP: [EIP-1559](https://eips.ethereum.org/EIPS/eip-1559)
*/
export class FeeMarket1559Tx extends BaseTransaction<TransactionType.FeeMarketEIP1559> {
export class FeeMarket1559Tx implements TransactionInterface<TransactionType.FeeMarketEIP1559> {
// implements EIP1559CompatibleTx<TransactionType.FeeMarketEIP1559>
public readonly chainId: bigint
public type: number = TransactionType.FeeMarketEIP1559 // 1559 tx type

// Tx data part (part of the RLP)
public readonly nonce!: bigint
public readonly gasLimit!: bigint
public readonly value!: bigint
public readonly data!: Uint8Array
public readonly to?: Address
public readonly accessList: AccessListBytes
public readonly AccessListJSON: AccessList
public readonly chainId: bigint
public readonly maxPriorityFeePerGas: bigint
public readonly maxFeePerGas: bigint

public readonly common: Common
// Props only for signed txs
public readonly v?: bigint
public readonly r?: bigint
public readonly s?: bigint

// End of Tx data part

public readonly AccessListJSON: AccessList

public readonly common!: Common

readonly txOptions!: TxOptions

readonly cache: TransactionCache = {}

/**
* List of tx type defining EIPs,
* e.g. 1559 (fee market) and 2930 (access lists)
* for FeeMarket1559Tx objects
*/
protected activeCapabilities: number[] = []

/**
* This constructor takes the values, validates them, assigns them and freezes the object.
Expand All @@ -56,16 +86,14 @@ export class FeeMarket1559Tx extends BaseTransaction<TransactionType.FeeMarketEI
* varying data types.
*/
public constructor(txData: TxData, opts: TxOptions = {}) {
super({ ...txData, type: TransactionType.FeeMarketEIP1559 }, opts)
sharedConstructor(this, { ...txData, type: TransactionType.FeeMarketEIP1559 }, opts)
const { chainId, accessList, maxFeePerGas, maxPriorityFeePerGas } = txData

this.common = opts.common?.copy() ?? new Common({ chain: this.DEFAULT_CHAIN })
if (chainId !== undefined && bytesToBigInt(toBytes(chainId)) !== this.common.chainId()) {
throw new Error(
`Common chain ID ${this.common.chainId} not matching the derived chain ID ${chainId}`,
)
}
this.common.updateParams(opts.params ?? paramsTx)
this.chainId = this.common.chainId()

if (!this.common.isActivatedEIP(1559)) {
Expand All @@ -83,20 +111,22 @@ export class FeeMarket1559Tx extends BaseTransaction<TransactionType.FeeMarketEI
this.maxFeePerGas = bytesToBigInt(toBytes(maxFeePerGas))
this.maxPriorityFeePerGas = bytesToBigInt(toBytes(maxPriorityFeePerGas))

this._validateCannotExceedMaxInteger({
valueBoundaryCheck({
maxFeePerGas: this.maxFeePerGas,
maxPriorityFeePerGas: this.maxPriorityFeePerGas,
})

validateNotArray(txData)

if (this.gasLimit * this.maxFeePerGas > MAX_INTEGER) {
const msg = this._errorMsg('gasLimit * maxFeePerGas cannot exceed MAX_INTEGER (2^256-1)')
const msg = Legacy.errorMsg(
this,
'gasLimit * maxFeePerGas cannot exceed MAX_INTEGER (2^256-1)',
)
throw new Error(msg)
}

if (this.maxFeePerGas < this.maxPriorityFeePerGas) {
const msg = this._errorMsg(
const msg = Legacy.errorMsg(
this,
'maxFeePerGas cannot be less than maxPriorityFeePerGas (The total must be the larger of the two)',
)
throw new Error(msg)
Expand All @@ -111,6 +141,26 @@ export class FeeMarket1559Tx extends BaseTransaction<TransactionType.FeeMarketEI
}
}

/**
* Checks if a tx type defining capability is active
* on a tx, for example the EIP-1559 fee market mechanism
* or the EIP-2930 access list feature.
*
* Note that this is different from the tx type itself,
* so EIP-2930 access lists can very well be active
* on an EIP-1559 tx for example.
*
* This method can be useful for feature checks if the
* tx type is unknown (e.g. when instantiated with
* the tx factory).
*
* See `Capabilities` in the `types` module for a reference
* on all supported capabilities.
*/
supports(capability: Capability) {
return this.activeCapabilities.includes(capability)
}

/**
* The amount of gas paid for the data in this tx
*/
Expand All @@ -134,6 +184,24 @@ export class FeeMarket1559Tx extends BaseTransaction<TransactionType.FeeMarketEI
return EIP1559.getUpfrontCost(this, baseFee)
}

/**
* The minimum gas limit which the tx to have to be valid.
* This covers costs as the standard fee (21000 gas), the data fee (paid for each calldata byte),
* the optional creation fee (if the transaction creates a contract), and if relevant the gas
* to be paid for access lists (EIP-2930) and authority lists (EIP-7702).
*/
getIntrinsicGas(): bigint {
return Legacy.getIntrinsicGas(this)
}

// TODO figure out if this is necessary
/**
* If the tx's `to` is to the creation address
*/
toCreationAddress(): boolean {
return Legacy.toCreationAddress(this)
}

/**
* Returns a Uint8Array Array of the raw Bytes of the EIP-1559 transaction, in order.
*
Expand Down Expand Up @@ -262,7 +330,7 @@ export class FeeMarket1559Tx extends BaseTransaction<TransactionType.FeeMarketEI
*/
toJSON(): JSONTx {
const accessListJSON = AccessLists.getAccessListJSON(this.accessList)
const baseJSON = super.toJSON()
const baseJSON = getBaseJSON(this)

return {
...baseJSON,
Expand All @@ -273,22 +341,41 @@ export class FeeMarket1559Tx extends BaseTransaction<TransactionType.FeeMarketEI
}
}

getValidationErrors(): string[] {
return Legacy.getValidationErrors(this)
}

isValid(): boolean {
return Legacy.isValid(this)
}

verifySignature(): boolean {
return Legacy.verifySignature(this)
}

getSenderAddress(): Address {
return Legacy.getSenderAddress(this)
}

sign(privateKey: Uint8Array): FeeMarket1559Tx {
return <FeeMarket1559Tx>Legacy.sign(this, privateKey)
}

public isSigned(): boolean {
const { v, r, s } = this
if (v === undefined || r === undefined || s === undefined) {
return false
} else {
return true
}
}

/**
* Return a compact error string representation of the object
*/
public errorStr() {
let errorStr = this._getSharedErrorPostfix()
let errorStr = Legacy.getSharedErrorPostfix(this)
errorStr += ` maxFeePerGas=${this.maxFeePerGas} maxPriorityFeePerGas=${this.maxPriorityFeePerGas}`
return errorStr
}

/**
* Internal helper function to create an annotated error message
*
* @param msg Base error message
* @hidden
*/
protected _errorMsg(msg: string) {
return Legacy.errorMsg(this, msg)
}
}
6 changes: 3 additions & 3 deletions packages/tx/src/2930/constructors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { bytesToBigInt, bytesToHex, equalsBytes, validateNoLeadingZeroes } from
import { TransactionType } from '../types.js'
import { txTypeBytes, validateNotArray } from '../util.js'

import { AccessList2930Transaction } from './tx.js'
import { AccessList2930Tx } from './tx.js'

import type { AccessList, TxOptions } from '../types.js'
import type { TxData, TxValuesArray } from './tx.js'
Expand All @@ -20,7 +20,7 @@ import type { TxData, TxValuesArray } from './tx.js'
* - All parameters are optional and have some basic default values
*/
export function createAccessList2930Tx(txData: TxData, opts: TxOptions = {}) {
return new AccessList2930Transaction(txData, opts)
return new AccessList2930Tx(txData, opts)
}

/**
Expand All @@ -43,7 +43,7 @@ export function createAccessList2930TxFromBytesArray(values: TxValuesArray, opts

const emptyAccessList: AccessList = []

return new AccessList2930Transaction(
return new AccessList2930Tx(
{
chainId: bytesToBigInt(chainId),
nonce,
Expand Down
2 changes: 1 addition & 1 deletion packages/tx/src/2930/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
export * from './constructors.js'
export { AccessList2930Transaction } from './tx.js'
export { AccessList2930Tx } from './tx.js'
Loading

0 comments on commit 5ccea5f

Please sign in to comment.