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

common: configure and fix kaustinen4 verkle testnet sync #3269

Merged
merged 53 commits into from
Mar 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
1befc1c
common: configure syncing kaustinen3 verkle testnet
g11tech Feb 3, 2024
594f94c
fix the vmexecution for verkle stateless init
g11tech Feb 3, 2024
e81515f
track and ignore the BLOCKHASH witness to avoid k3 blockhash issues
g11tech Feb 3, 2024
b890167
remove the tx to/from access fees
g11tech Feb 3, 2024
251f388
setup kaunstinen3 block15 stateless test execution for debugging
g11tech Feb 3, 2024
a9e5dc8
fix charging and waiving of tx origin/dest access fees
g11tech Feb 3, 2024
1c5f0b0
configure to run kaustinen4
g11tech Feb 6, 2024
dc1306f
setup to test the failing block 368
g11tech Feb 6, 2024
1c34416
debug and fix the code chunking boundary conditions
g11tech Feb 6, 2024
2cfa736
skip missing chunk lookup on the invalid opcode if code not loaded fr…
g11tech Feb 6, 2024
b17a392
setup to debug the failing block374 in spec
g11tech Feb 6, 2024
d8ffbb2
fix genesis spec
g11tech Feb 6, 2024
7523f65
add block353 to the test spec and help debug nethermind/besu for acce…
g11tech Feb 8, 2024
d55385f
add partial account functionality and set stateless verkle manager to…
g11tech Feb 9, 2024
7222037
load all partial basic data in account and use the same in the get co…
g11tech Feb 9, 2024
d859671
debug and fix block372 working including stem hack for k4
g11tech Feb 9, 2024
5726e1f
sync further and now setup failing block 479 for debugging
g11tech Feb 9, 2024
5b5eaef
change stem formation for addresses less than 20 bytes to match kaust…
g11tech Mar 2, 2024
d5705df
update test to test more than one block
g11tech Mar 2, 2024
d8df57e
add capability to test spec run blocks off beacon url
g11tech Mar 3, 2024
eab6a46
debug and handle if CL returns payload with snake case witness
g11tech Mar 3, 2024
4c0e4ab
fix the comment
g11tech Mar 4, 2024
d2142a9
vm: clear verkle cache in runBlock if opt is true
gabrocheleau Mar 5, 2024
547e092
add functionality to start stateless execution from any block in chain
g11tech Mar 5, 2024
ee9800a
chore: merge with master
gabrocheleau Mar 5, 2024
1385262
configure client to decouple execution and keep syncing despite chain…
g11tech Mar 6, 2024
a9bc254
modify the client to continue syncing ignoring block failures
g11tech Mar 6, 2024
ed1f1bd
save failing blocks if indicated by the flag
g11tech Mar 6, 2024
7e7bf2a
update test to pick generated testcases from dir
g11tech Mar 7, 2024
f8a1db6
debug and add missing data in toexecutionwitness
g11tech Mar 7, 2024
aec1f6f
fix the test spec for various scenarios
g11tech Mar 7, 2024
8067869
add witness errors to the debug log
g11tech Mar 7, 2024
8adb7a9
debug and fix the issue for slot mismatch of a valid block - 521
g11tech Mar 7, 2024
d06b42c
add hack to get over the stem matching issue of kaustinen4 by brutefo…
g11tech Mar 8, 2024
3244d86
allow one to provide witnesses to a rlped block via opts
g11tech Mar 17, 2024
4e27c76
restore stem calc to correct one
g11tech Mar 17, 2024
7ed686c
apply fix for codechunk comparision and better post state mismatches …
g11tech Mar 17, 2024
aaa5839
setup the kaustinen4 spec test to use geth test vectors
g11tech Mar 17, 2024
92e0dc1
remove the code creation cost and fix the code creation write cost an…
g11tech Mar 17, 2024
8c3d7c1
fix charging code read acceses for codecopy if from calldata and remo…
g11tech Mar 17, 2024
a3ca621
debug and match the create opcode gas consumptions
g11tech Mar 18, 2024
bd20bb9
commit new vestors and a fix for the contract create costs to not cha…
g11tech Mar 21, 2024
2e1b158
add blockhash set/get accesses and remove ignoring them from post sta…
g11tech Mar 21, 2024
e9973ef
remove cold cost for sload and sstore
g11tech Mar 21, 2024
b392741
Merge remote-tracking branch 'origin/master' into kaustinen3
g11tech Mar 25, 2024
d5f8a96
debug and fix 3 testcases in verkle stateless manager spec
g11tech Mar 25, 2024
3487ed7
fix rest of spec
g11tech Mar 26, 2024
e6b3f7d
make the get contract size optional in interface
g11tech Mar 26, 2024
326eff0
fix lint
g11tech Mar 26, 2024
357496d
fix vm api test
g11tech Mar 26, 2024
44f06c1
restore kaustinen2 genesis for preimages spec
g11tech Mar 26, 2024
0395441
Merge remote-tracking branch 'origin/master' into kaustinen3
g11tech Mar 26, 2024
d7e2635
client spec and lint fixes
g11tech Mar 26, 2024
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
47 changes: 41 additions & 6 deletions packages/block/src/block.ts
Original file line number Diff line number Diff line change
Expand Up @@ -228,12 +228,16 @@
// executionWitness are not part of the EL fetched blocks via eth_ bodies method
// they are currently only available via the engine api constructed blocks
let executionWitness
if (header.common.isActivatedEIP(6800) && executionWitnessBytes !== undefined) {
executionWitness = JSON.parse(bytesToUtf8(RLP.decode(executionWitnessBytes) as Uint8Array))
} else {
// don't assign default witness if eip 6800 is implemented as it leads to incorrect
// assumptions while executing the block. if not present in input implies its unavailable
executionWitness = null
if (header.common.isActivatedEIP(6800)) {
if (executionWitnessBytes !== undefined) {
executionWitness = JSON.parse(bytesToUtf8(RLP.decode(executionWitnessBytes) as Uint8Array))
} else if (opts?.executionWitness !== undefined) {
executionWitness = opts.executionWitness
} else {
// don't assign default witness if eip 6800 is implemented as it leads to incorrect
// assumptions while executing the block. if not present in input implies its unavailable
executionWitness = null
}

Check warning on line 240 in packages/block/src/block.ts

View check run for this annotation

Codecov / codecov/patch

packages/block/src/block.ts#L232-L240

Added lines #L232 - L240 were not covered by tests
}

return new Block(header, transactions, uncleHeaders, withdrawals, opts, executionWitness)
Expand Down Expand Up @@ -800,6 +804,37 @@
}
}

toExecutionPayload(): ExecutionPayload {
const blockJson = this.toJSON()
const header = blockJson.header!
const transactions = this.transactions.map((tx) => bytesToHex(tx.serialize())) ?? []
const withdrawalsArr = blockJson.withdrawals ? { withdrawals: blockJson.withdrawals } : {}

const executionPayload: ExecutionPayload = {
blockNumber: header.number!,
parentHash: header.parentHash!,
feeRecipient: header.coinbase!,
stateRoot: header.stateRoot!,
receiptsRoot: header.receiptTrie!,
logsBloom: header.logsBloom!,
gasLimit: header.gasLimit!,
gasUsed: header.gasUsed!,
timestamp: header.timestamp!,
extraData: header.extraData!,
baseFeePerGas: header.baseFeePerGas!,
blobGasUsed: header.blobGasUsed,
excessBlobGas: header.excessBlobGas,
blockHash: bytesToHex(this.hash()),
prevRandao: header.mixHash!,
transactions,
...withdrawalsArr,
parentBeaconBlockRoot: header.parentBeaconBlockRoot,
executionWitness: this.executionWitness,
}

return executionPayload
}

Check warning on line 836 in packages/block/src/block.ts

View check run for this annotation

Codecov / codecov/patch

packages/block/src/block.ts#L808-L836

Added lines #L808 - L836 were not covered by tests

/**
* Return a compact error string representation of the object
*/
Expand Down
64 changes: 61 additions & 3 deletions packages/block/src/from-beacon-payload.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { bigIntToHex } from '@ethereumjs/util'

import type { ExecutionPayload, VerkleExecutionWitness } from './types.js'
import type { PrefixedHexString } from '@ethereumjs/util'

type BeaconWithdrawal = {
index: string
Expand Down Expand Up @@ -34,6 +35,59 @@
execution_witness?: VerkleExecutionWitness
}

type VerkleProofSnakeJson = {
commitments_by_path: PrefixedHexString[]
d: PrefixedHexString
depth_extension_present: PrefixedHexString
ipa_proof: {
cl: PrefixedHexString[]
cr: PrefixedHexString[]
final_evaluation: PrefixedHexString
}
other_stems: PrefixedHexString[]
}

type VerkleStateDiffSnakeJson = {
stem: PrefixedHexString
suffix_diffs: {
current_value: PrefixedHexString | null
new_value: PrefixedHexString | null
suffix: number | string
}[]
}

type VerkleExecutionWitnessSnakeJson = {
state_diff: VerkleStateDiffSnakeJson[]
verkle_proof: VerkleProofSnakeJson
}

function parseExecutionWitnessFromSnakeJson({
state_diff,
verkle_proof,
}: VerkleExecutionWitnessSnakeJson): VerkleExecutionWitness {
return {
stateDiff: state_diff.map(({ stem, suffix_diffs }) => ({
stem,
suffixDiffs: suffix_diffs.map(({ current_value, new_value, suffix }) => ({
currentValue: current_value,
newValue: new_value,
suffix,
})),
})),
verkleProof: {
commitmentsByPath: verkle_proof.commitments_by_path,
d: verkle_proof.d,
depthExtensionPresent: verkle_proof.depth_extension_present,
ipaProof: {
cl: verkle_proof.ipa_proof.cl,
cr: verkle_proof.ipa_proof.cr,
finalEvaluation: verkle_proof.ipa_proof.final_evaluation,
},
otherStems: verkle_proof.other_stems,
},
}
}

Check warning on line 89 in packages/block/src/from-beacon-payload.ts

View check run for this annotation

Codecov / codecov/patch

packages/block/src/from-beacon-payload.ts#L64-L89

Added lines #L64 - L89 were not covered by tests

/**
* Converts a beacon block execution payload JSON object {@link BeaconPayloadJson} to the {@link ExecutionPayload} data needed to construct a {@link Block}.
* The JSON data can be retrieved from a consensus layer (CL) client on this Beacon API `/eth/v2/beacon/blocks/[block number]`
Expand Down Expand Up @@ -75,9 +129,13 @@
executionPayload.parentBeaconBlockRoot = payload.parent_beacon_block_root
}
if (payload.execution_witness !== undefined && payload.execution_witness !== null) {
// the casing structure in payload is already camel case, might be updated in
// kaustinen relaunch
executionPayload.executionWitness = payload.execution_witness
// the casing structure in payload could be camel case or snake depending upon the CL
executionPayload.executionWitness =
payload.execution_witness.verkleProof !== undefined
? payload.execution_witness
: parseExecutionWitnessFromSnakeJson(
payload.execution_witness as unknown as VerkleExecutionWitnessSnakeJson
)

Check warning on line 138 in packages/block/src/from-beacon-payload.ts

View check run for this annotation

Codecov / codecov/patch

packages/block/src/from-beacon-payload.ts#L136-L138

Added lines #L136 - L138 were not covered by tests
}

return executionPayload
Expand Down
2 changes: 2 additions & 0 deletions packages/block/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ export interface BlockOptions {
* Skip consensus format validation checks on header if set. Defaults to false.
*/
skipConsensusFormatValidation?: boolean

executionWitness?: VerkleExecutionWitness
}

export interface VerkleProof {
Expand Down
78 changes: 76 additions & 2 deletions packages/client/bin/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,16 @@ const args: ClientOpts = yargs
'Block number to start syncing from. Must be lower than the local chain tip. Note: this is destructive and removes blocks from the blockchain, please back up your datadir before using.',
number: true,
})
.option('startExecutionFrom', {
describe:
'Block number to start/restart execution from. For merkle based state, parent state should be present in the the db while in verkle stateless mode the chain should be synced till the block and witnesses available this block onwards',
number: true,
})
.option('startExecution', {
describe:
'Start execution of unexecuted blocks without waiting for the CL fcU, set to `true` if `startExecutionFrom` provided',
boolean: true,
})
.option('isSingleNode', {
describe:
'To run client in single node configuration without need to discover the sync height from peer. Particularly useful in test configurations. This flag is automically activated in the "dev" mode',
Expand Down Expand Up @@ -420,6 +430,15 @@ const args: ClientOpts = yargs
'Skip executing blocks in new payload calls in engine, alias for --engineNewpayloadMaxExecute=0 and overrides any engineNewpayloadMaxExecute if also provided',
boolean: true,
})
.option('ignoreStatelessInvalidExecs', {
describe:
'Ignore stateless execution failures and keep moving the vm execution along using execution witnesses available in block (verkle). Sets/overrides --statelessVerkle=true and --engineNewpayloadMaxExecute=0 to prevent engine newPayload direct block execution where block execution faliures may stall the CL client. Useful for debugging the verkle. If provided a valid filename as arg, the invalid blocks will be stored there which one may use later for debugging',
coerce: (arg: string | boolean) =>
typeof arg === 'string' && arg !== 'true' && arg !== 'false'
? path.resolve(arg)
: arg === true || arg === 'true',
hidden: true,
})
.option('useJsCrypto', {
describe: 'Use pure Javascript cryptography functions',
boolean: true,
Expand Down Expand Up @@ -525,6 +544,52 @@ async function startBlock(client: EthereumClient) {
}
}

async function startExecutionFrom(client: EthereumClient) {
if (args.startExecutionFrom === undefined) return
const startExecutionFrom = BigInt(args.startExecutionFrom)

const height = client.chain.headers.height
if (height < startExecutionFrom) {
logger.error(`Cannot start merkle chain higher than current height ${height}`)
process.exit()
}

const startExecutionBlock = await client.chain.getBlock(startExecutionFrom)
const startExecutionParent = await client.chain.getBlock(startExecutionBlock.header.parentHash)
const startExecutionParentTd = await client.chain.getTd(
startExecutionParent.hash(),
startExecutionParent.header.number
)

const startExecutionHardfork = client.config.execCommon.getHardforkBy({
blockNumber: startExecutionBlock.header.number,
td: startExecutionParentTd,
timestamp: startExecutionBlock.header.timestamp,
})

if (
client.config.execCommon.hardforkGteHardfork(startExecutionHardfork, Hardfork.Prague) &&
client.config.statelessVerkle
) {
// for stateless verkle sync execution witnesses are available and hence we can blindly set the vmHead
// to startExecutionParent's hash
try {
await client.chain.blockchain.setIteratorHead('vm', startExecutionParent.hash())
await client.chain.update(false)
logger.info(
`vmHead set to ${client.chain.headers.height} for starting stateless execution at hardfork=${startExecutionHardfork}`
)
} catch (err: any) {
logger.error(`Error setting vmHead for starting stateless execution: ${err}`)
process.exit()
}
} else {
// we need parent state availability to set the vmHead to the parent
logger.error(`Stateful execution reset not implemented at hardfork=${startExecutionHardfork}`)
process.exit()
}
}

/**
* Starts and returns the {@link EthereumClient}
*/
Expand Down Expand Up @@ -601,6 +666,9 @@ async function startClient(
if (typeof args.startBlock === 'number') {
await startBlock(client)
}
if (typeof args.startExecutionFrom === 'number') {
await startExecutionFrom(client)
}

// update client's sync status and start txpool if synchronized
client.config.updateSynchronizedState(client.chain.headers.latest)
Expand Down Expand Up @@ -959,6 +1027,7 @@ async function run() {
const multiaddrs = args.multiaddrs !== undefined ? parseMultiaddrs(args.multiaddrs) : undefined
const mine = args.mine !== undefined ? args.mine : args.dev !== undefined
const isSingleNode = args.isSingleNode !== undefined ? args.isSingleNode : args.dev !== undefined

const config = new Config({
accounts,
bootnodes,
Expand Down Expand Up @@ -997,8 +1066,13 @@ async function run() {
useStringValueTrieDB: args.useStringValueTrieDB,
txLookupLimit: args.txLookupLimit,
pruneEngineCache: args.pruneEngineCache,
statelessVerkle: args.statelessVerkle,
engineNewpayloadMaxExecute: args.skipEngineExec === true ? 0 : args.engineNewpayloadMaxExecute,
statelessVerkle: args.ignoreStatelessInvalidExecs !== false ? true : args.statelessVerkle,
startExecution: args.startExecutionFrom !== undefined ? true : args.startExecution,
engineNewpayloadMaxExecute:
args.ignoreStatelessInvalidExecs !== false || args.skipEngineExec === true
? 0
: args.engineNewpayloadMaxExecute,
ignoreStatelessInvalidExecs: args.ignoreStatelessInvalidExecs,
})
config.events.setMaxListeners(50)
config.events.on(Event.SERVER_LISTENING, (details) => {
Expand Down
6 changes: 6 additions & 0 deletions packages/client/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,8 @@ export interface ConfigOptions {
* Enables stateless verkle block execution (default: false)
*/
statelessVerkle?: boolean
startExecution?: boolean
ignoreStatelessInvalidExecs?: boolean | string
}

export class Config {
Expand Down Expand Up @@ -442,6 +444,8 @@ export class Config {
public readonly savePreimages: boolean

public readonly statelessVerkle: boolean
public readonly startExecution: boolean
public readonly ignoreStatelessInvalidExecs: boolean | string

public synchronized: boolean
public lastsyncronized?: boolean
Expand Down Expand Up @@ -529,6 +533,8 @@ export class Config {
this.useStringValueTrieDB = options.useStringValueTrieDB ?? false

this.statelessVerkle = options.statelessVerkle ?? true
this.startExecution = options.startExecution ?? false
this.ignoreStatelessInvalidExecs = options.ignoreStatelessInvalidExecs ?? false

// Start it off as synchronized if this is configured to mine or as single node
this.synchronized = this.isSingleNode ?? this.mine
Expand Down
Loading
Loading