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

poc provable web3: implement various EIPs for a more provable protocol #3849

Draft
wants to merge 4 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
110 changes: 110 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions packages/block/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
"tsc": "../../config/cli/ts-compile.sh"
},
"dependencies": {
"@chainsafe/ssz": "^0.18.0",
"@ethereumjs/common": "^5.0.0-alpha.1",
"@ethereumjs/rlp": "^6.0.0-alpha.1",
"@ethereumjs/mpt": "^7.0.0-alpha.1",
Expand Down
52 changes: 21 additions & 31 deletions packages/block/src/block/block.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,7 @@ import { ConsensusType } from '@ethereumjs/common'
import { MerklePatriciaTrie } from '@ethereumjs/mpt'
import { RLP } from '@ethereumjs/rlp'
import { Blob4844Tx, Capability } from '@ethereumjs/tx'
import {
BIGINT_0,
KECCAK256_RLP,
KECCAK256_RLP_ARRAY,
bytesToHex,
equalsBytes,
} from '@ethereumjs/util'
import { BIGINT_0, KECCAK256_RLP_ARRAY, bytesToHex, equalsBytes } from '@ethereumjs/util'
import { keccak256 } from 'ethereum-cryptography/keccak.js'
import { sha256 } from 'ethereum-cryptography/sha256'

Expand All @@ -18,6 +12,7 @@ import { sha256 } from 'ethereum-cryptography/sha256'
// TODO: See if there is an easier way to achieve the same result.
// See: https://github.com/microsoft/TypeScript/issues/47558
// (situation will eventually improve on Typescript and/or Eslint update)
import { genTransactionsSszRoot, genWithdrawalsSszRoot } from '../helpers.js'
import {
genTransactionsTrieRoot,
genWithdrawalsTrieRoot,
Expand Down Expand Up @@ -199,10 +194,9 @@ export class Block {
* Generates transaction trie for validation.
*/
async genTxTrie(): Promise<Uint8Array> {
return genTransactionsTrieRoot(
this.transactions,
new MerklePatriciaTrie({ common: this.common }),
)
return this.common.isActivatedEIP(6493)
? genTransactionsSszRoot(this.transactions)
: genTransactionsTrieRoot(this.transactions, new MerklePatriciaTrie({ common: this.common }))
}

/**
Expand All @@ -211,16 +205,10 @@ export class Block {
* @returns True if the transaction trie is valid, false otherwise
*/
async transactionsTrieIsValid(): Promise<boolean> {
let result
if (this.transactions.length === 0) {
result = equalsBytes(this.header.transactionsTrie, KECCAK256_RLP)
return result
}

if (this.cache.txTrieRoot === undefined) {
this.cache.txTrieRoot = await this.genTxTrie()
}
result = equalsBytes(this.cache.txTrieRoot, this.header.transactionsTrie)
const result = equalsBytes(this.cache.txTrieRoot, this.header.transactionsTrie)
return result
}

Expand Down Expand Up @@ -319,7 +307,9 @@ export class Block {
}

if (!(await this.transactionsTrieIsValid())) {
const msg = this._errorMsg('invalid transaction trie')
const msg = this._errorMsg(
`invalid transaction trie expected=${bytesToHex(this.cache.txTrieRoot!)}`,
)
throw new Error(msg)
}

Expand Down Expand Up @@ -409,6 +399,12 @@ export class Block {
return equalsBytes(this.keccakFunction(raw), this.header.uncleHash)
}

async genWithdrawalsTrie(): Promise<Uint8Array> {
return this.common.isActivatedEIP(6493)
? genWithdrawalsSszRoot(this.withdrawals!)
: genWithdrawalsTrieRoot(this.withdrawals!, new MerklePatriciaTrie({ common: this.common }))
}

/**
* Validates the withdrawal root
* @returns true if the withdrawals trie root is valid, false otherwise
Expand All @@ -418,19 +414,10 @@ export class Block {
throw new Error('EIP 4895 is not activated')
}

let result
if (this.withdrawals!.length === 0) {
result = equalsBytes(this.header.withdrawalsRoot!, KECCAK256_RLP)
return result
}

if (this.cache.withdrawalsTrieRoot === undefined) {
this.cache.withdrawalsTrieRoot = await genWithdrawalsTrieRoot(
this.withdrawals!,
new MerklePatriciaTrie({ common: this.common }),
)
this.cache.withdrawalsTrieRoot = await this.genWithdrawalsTrie()
}
result = equalsBytes(this.cache.withdrawalsTrieRoot, this.header.withdrawalsRoot!)
const result = equalsBytes(this.cache.withdrawalsTrieRoot, this.header.withdrawalsRoot!)
return result
}

Expand Down Expand Up @@ -498,7 +485,9 @@ export class Block {
toExecutionPayload(): ExecutionPayload {
const blockJSON = this.toJSON()
const header = blockJSON.header!
const transactions = this.transactions.map((tx) => bytesToHex(tx.serialize())) ?? []
const transactions = this.common.isActivatedEIP(6493)
? this.transactions.map((tx) => tx.toExecutionPayloadTx())
: this.transactions.map((tx) => bytesToHex(tx.serialize()))
const withdrawalsArr = blockJSON.withdrawals ? { withdrawals: blockJSON.withdrawals } : {}

const executionPayload: ExecutionPayload = {
Expand All @@ -522,6 +511,7 @@ export class Block {
parentBeaconBlockRoot: header.parentBeaconBlockRoot,
requestsHash: header.requestsHash,
executionWitness: this.executionWitness,
systemLogsRoot: this.common.isActivatedEIP(6493) ? header.systemLogsRoot : undefined,
}

return executionPayload
Expand Down
45 changes: 33 additions & 12 deletions packages/block/src/block/constructors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
type TxOptions,
createTx,
createTxFromBlockBodyData,
createTxFromExecutionPayloadTx,
createTxFromRLP,
normalizeTxParams,
} from '@ethereumjs/tx'
Expand All @@ -21,7 +22,12 @@ import {
} from '@ethereumjs/util'

import { generateCliqueBlockExtraData } from '../consensus/clique.js'
import { genTransactionsTrieRoot, genWithdrawalsTrieRoot } from '../helpers.js'
import {
genTransactionsSszRoot,
genTransactionsTrieRoot,
genWithdrawalsSszRoot,
genWithdrawalsTrieRoot,
} from '../helpers.js'
import {
Block,
createBlockHeader,
Expand All @@ -41,6 +47,7 @@ import type {
JSONRPCBlock,
WithdrawalsBytes,
} from '../types.js'
import type { Common } from '@ethereumjs/common'
import type { TypedTransaction } from '@ethereumjs/tx'
import type { EthersProvider, PrefixedHexString, WithdrawalBytes } from '@ethereumjs/util'

Expand Down Expand Up @@ -322,7 +329,7 @@ export const createBlockFromJSONRPCProvider = async (
*/
export async function createBlockFromExecutionPayload(
payload: ExecutionPayload,
opts?: BlockOptions,
opts: BlockOptions & { common: Common },
): Promise<Block> {
const {
blockNumber: number,
Expand All @@ -335,25 +342,39 @@ export async function createBlockFromExecutionPayload(
} = payload

const txs = []
for (const [index, serializedTx] of transactions.entries()) {
for (const [index, serializedTxOrPayload] of transactions.entries()) {
try {
const tx = createTxFromRLP(hexToBytes(serializedTx as PrefixedHexString), {
common: opts?.common,
})
let tx
if (opts.common.isActivatedEIP(6493)) {
if (typeof serializedTxOrPayload === 'string') {
throw Error('EIP 6493 activated for transaction bytes')
}
tx = createTxFromExecutionPayloadTx(serializedTxOrPayload, {
common: opts?.common,
})
} else {
if (typeof serializedTxOrPayload !== 'string') {
throw Error('EIP 6493 not activated for transaction payload')
}
tx = createTxFromRLP(hexToBytes(serializedTxOrPayload as PrefixedHexString), {
common: opts?.common,
})
}
txs.push(tx)
} catch (error) {
const validationError = `Invalid tx at index ${index}: ${error}`
throw validationError
}
}

const transactionsTrie = await genTransactionsTrieRoot(
txs,
new MerklePatriciaTrie({ common: opts?.common }),
)
const transactionsTrie = opts.common.isActivatedEIP(6493)
? await genTransactionsSszRoot(txs)
: await genTransactionsTrieRoot(txs, new MerklePatriciaTrie({ common: opts?.common }))
const withdrawals = withdrawalsData?.map((wData) => createWithdrawal(wData))
const withdrawalsRoot = withdrawals
? await genWithdrawalsTrieRoot(withdrawals, new MerklePatriciaTrie({ common: opts?.common }))
? opts.common.isActivatedEIP(6493)
? genWithdrawalsSszRoot(withdrawals)
: await genWithdrawalsTrieRoot(withdrawals, new MerklePatriciaTrie({ common: opts?.common }))
: undefined

const header: HeaderData = {
Expand Down Expand Up @@ -393,7 +414,7 @@ export async function createBlockFromExecutionPayload(
*/
export async function createBlockFromBeaconPayloadJSON(
payload: BeaconPayloadJSON,
opts?: BlockOptions,
opts: BlockOptions & { common: Common },
): Promise<Block> {
const executionPayload = executionPayloadFromBeaconPayload(payload)
return createBlockFromExecutionPayload(executionPayload, opts)
Expand Down
Loading
Loading