Skip to content

Commit

Permalink
client: integrate snapsync on experimental basis
Browse files Browse the repository at this point in the history
  • Loading branch information
g11tech committed Sep 22, 2023
1 parent e1af691 commit 2e13846
Show file tree
Hide file tree
Showing 11 changed files with 160 additions and 90 deletions.
12 changes: 3 additions & 9 deletions packages/client/bin/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -319,13 +319,8 @@ const args: ClientOpts = yargs(hideBin(process.argv))
boolean: true,
default: true,
})
.option('disableBeaconSync', {
describe:
'Disables beacon (optimistic) sync if the CL provides blocks at the head of the chain',
boolean: true,
})
.option('forceSnapSync', {
describe: 'Force a snap sync run (for testing and development purposes)',
.option('enableSnapSync', {
describe: 'Enable snap state sync (for testing and development purposes)',
boolean: true,
})
.option('prefixStorageTrieKeys', {
Expand Down Expand Up @@ -841,9 +836,8 @@ async function run() {
port: args.port,
saveReceipts: args.saveReceipts,
syncmode: args.sync,
disableBeaconSync: args.disableBeaconSync,
forceSnapSync: args.forceSnapSync,
prefixStorageTrieKeys: args.prefixStorageTrieKeys,
enableSnapSync: args.enableSnapSync,
transports: args.transports,
txLookupLimit: args.txLookupLimit,
})
Expand Down
32 changes: 13 additions & 19 deletions packages/client/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,22 +43,11 @@ export interface ConfigOptions {
syncmode?: SyncMode

/**
* Whether to disable beacon (optimistic) sync if CL provides
* blocks at the head of chain.
* Whether to enable and run snapSync, currently experimental
*
* Default: false
*/
disableBeaconSync?: boolean

/**
* Whether to test and run snapSync. When fully ready, this needs to
* be replaced by a more sophisticated condition based on how far back we are
* from the head, and how to run it in conjunction with the beacon sync
* blocks at the head of chain.
*
* Default: false
*/
forceSnapSync?: boolean
enableSnapSync?: boolean

/**
* A temporary option to offer backward compatibility with already-synced databases that are
Expand Down Expand Up @@ -322,6 +311,8 @@ export interface ConfigOptions {
engineNewpayloadMaxExecute?: number

maxStorageRange?: bigint

snapAvailabilityDepth?: bigint
}

export class Config {
Expand Down Expand Up @@ -361,6 +352,7 @@ export class Config {
// engine new payload calls can come in batch of 64, keeping 128 as the lookup factor
public static readonly ENGINE_PARENTLOOKUP_MAX_DEPTH = 128
public static readonly ENGINE_NEWPAYLOAD_MAX_EXECUTE = 2
public static readonly SNAP_AVAILABILITY_DEPTH = BigInt(128)

public readonly logger: Logger
public readonly syncmode: SyncMode
Expand Down Expand Up @@ -404,18 +396,20 @@ export class Config {
public readonly syncedStateRemovalPeriod: number
public readonly engineParentLookupMaxDepth: number
public readonly engineNewpayloadMaxExecute: number
public readonly snapAvailabilityDepth: bigint

public readonly disableBeaconSync: boolean
public readonly forceSnapSync: boolean
// Just a development only flag, will/should be removed
public readonly disableSnapSync: boolean = false
public readonly prefixStorageTrieKeys: boolean
// Defaulting to false as experimental as of now
public readonly enableSnapSync: boolean

public synchronized: boolean
/** lastSyncDate in ms */
public lastSyncDate: number
/** Best known block height */
public syncTargetHeight?: bigint
/** for snapsync */
public snapTargetHeight?: bigint
public snapTargetRoot?: Uint8Array
/** Client is in the process of shutting down */
public shutdown: boolean = false

Expand Down Expand Up @@ -478,10 +472,10 @@ export class Config {
options.engineParentLookupMaxDepth ?? Config.ENGINE_PARENTLOOKUP_MAX_DEPTH
this.engineNewpayloadMaxExecute =
options.engineNewpayloadMaxExecute ?? Config.ENGINE_NEWPAYLOAD_MAX_EXECUTE
this.snapAvailabilityDepth = options.snapAvailabilityDepth ?? Config.SNAP_AVAILABILITY_DEPTH

this.disableBeaconSync = options.disableBeaconSync ?? false
this.forceSnapSync = options.forceSnapSync ?? false
this.prefixStorageTrieKeys = options.prefixStorageTrieKeys ?? true
this.enableSnapSync = options.enableSnapSync ?? false

// Start it off as synchronized if this is configured to mine or as single node
this.synchronized = this.isSingleNode ?? this.mine
Expand Down
2 changes: 1 addition & 1 deletion packages/client/src/rpc/modules/engine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -936,7 +936,7 @@ export class Engine {
// It is possible that newPayload didn't start beacon sync as the payload it was asked to
// evaluate didn't require syncing beacon. This can happen if the EL<>CL starts and CL
// starts from a bit behind like how lodestar does
if (!this.service.beaconSync && !this.config.disableBeaconSync) {
if (!this.service.beaconSync) {
await this.service.switchToBeaconSync()
}

Expand Down
102 changes: 61 additions & 41 deletions packages/client/src/service/fullethereumservice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,17 @@ interface FullEthereumServiceOptions extends ServiceOptions {
* @memberof module:service
*/
export class FullEthereumService extends Service {
public synchronizer?: BeaconSynchronizer | FullSynchronizer | SnapSynchronizer
/* synchronizer for syncing the chain */
public synchronizer?: BeaconSynchronizer | FullSynchronizer
public lightserv: boolean
public miner: Miner | undefined
public execution: VMExecution
public txPool: TxPool
public skeleton?: Skeleton

// objects dealing with state
public snapsync?: SnapSynchronizer
public execution: VMExecution

/**
* Create new ETH service
*/
Expand All @@ -48,63 +52,67 @@ export class FullEthereumService extends Service {

this.config.logger.info('Full sync mode')

const { metaDB } = options
if (metaDB !== undefined) {
this.skeleton = new Skeleton({
config: this.config,
chain: this.chain,
metaDB,
})
}

this.execution = new VMExecution({
config: options.config,
stateDB: options.stateDB,
metaDB: options.metaDB,
metaDB,
chain: this.chain,
})

this.snapsync = this.config.enableSnapSync
? new SnapSynchronizer({
config: this.config,
pool: this.pool,
chain: this.chain,
interval: this.interval,
skeleton: this.skeleton,
execution: this.execution,
})
: undefined

this.txPool = new TxPool({
config: this.config,
service: this,
})

const metaDB = (this.execution as any).metaDB
if (metaDB !== undefined) {
this.skeleton = new Skeleton({
config: this.config,
chain: this.chain,
metaDB,
})
}

// This flag is just to run and test snap sync, when fully ready, this needs to
// be replaced by a more sophisticated condition based on how far back we are
// from the head, and how to run it in conjunction with the beacon sync
if (this.config.forceSnapSync) {
this.synchronizer = new SnapSynchronizer({
config: this.config,
pool: this.pool,
chain: this.chain,
interval: this.interval,
})
} else {
if (this.config.syncmode === SyncMode.Full) {
if (this.config.chainCommon.gteHardfork(Hardfork.Paris) === true) {
if (!this.config.disableBeaconSync) {
void this.switchToBeaconSync()
}
this.synchronizer = new BeaconSynchronizer({
config: this.config,

Check warning on line 90 in packages/client/src/service/fullethereumservice.ts

View check run for this annotation

Codecov / codecov/patch

packages/client/src/service/fullethereumservice.ts#L89-L90

Added lines #L89 - L90 were not covered by tests
pool: this.pool,
chain: this.chain,
interval: this.interval,
execution: this.execution,
skeleton: this.skeleton!,
})
this.config.logger.info(`Post-merge 🐼 client mode: run with CL client.`)
} else {
if (this.config.syncmode === SyncMode.Full) {
this.synchronizer = new FullSynchronizer({
this.synchronizer = new FullSynchronizer({
config: this.config,
pool: this.pool,
chain: this.chain,
txPool: this.txPool,
execution: this.execution,
interval: this.interval,
})

if (this.config.mine) {
this.miner = new Miner({
config: this.config,
pool: this.pool,
chain: this.chain,
txPool: this.txPool,
execution: this.execution,
interval: this.interval,
service: this,
})
}
}
}

if (this.config.mine) {
this.miner = new Miner({
config: this.config,
service: this,
})
}
}

/**
Expand Down Expand Up @@ -171,7 +179,15 @@ export class FullEthereumService extends Service {
if (txs[0].length > 0) this.txPool.sendNewTxHashes(txs, [peer])
})
await super.open()
await this.execution.open()

// open snapsync instead of execution if instantiated
// it will open execution when done (or if doesn't need to snap sync)
if (this.snapsync !== undefined) {
await this.snapsync.open()
} else {
await this.execution.open()
}

Check warning on line 190 in packages/client/src/service/fullethereumservice.ts

View check run for this annotation

Codecov / codecov/patch

packages/client/src/service/fullethereumservice.ts#L182-L190

Added lines #L182 - L190 were not covered by tests
this.txPool.open()
if (this.config.mine) {
// Start the TxPool immediately if mining
Expand Down Expand Up @@ -203,7 +219,11 @@ export class FullEthereumService extends Service {
this.txPool.stop()
this.miner?.stop()
await this.synchronizer?.stop()

await this.snapsync?.stop()
// independently close execution even if it might have been opened by snapsync
await this.execution.stop()

await super.stop()
return true
}
Expand Down
10 changes: 10 additions & 0 deletions packages/client/src/service/skeleton.ts
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,16 @@ export class Skeleton extends MetaDBManager {
return this.status.progress.subchains[0]
}

async headHash(): Promise<Uint8Array | undefined> {
const subchain = this.bounds()
if (subchain !== undefined) {
const headBlock = await this.getBlock(subchain.head)
if (headBlock) {
return headBlock.hash()
}
}
}

Check warning on line 408 in packages/client/src/service/skeleton.ts

View check run for this annotation

Codecov / codecov/patch

packages/client/src/service/skeleton.ts#L405-L408

Added lines #L405 - L408 were not covered by tests
private async trySubChainsMerge(): Promise<boolean> {
let merged = false
let edited = false
Expand Down
11 changes: 11 additions & 0 deletions packages/client/src/sync/fetcher/accountfetcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import type { EventBusType } from '../../types'
import type { FetcherOptions } from './fetcher'
import type { StorageRequest } from './storagefetcher'
import type { Job } from './types'
import type { DefaultStateManager } from '@ethereumjs/statemanager'
import type { Debugger } from 'debug'
const { debug: createDebugLogger } = debugDefault

Expand All @@ -51,6 +52,8 @@ export interface AccountFetcherOptions extends FetcherOptions {

/** Destroy fetcher once all tasks are done */
destroyWhenDone?: boolean

stateManager: DefaultStateManager
}

// root comes from block?
Expand Down Expand Up @@ -112,6 +115,7 @@ export function snapFetchersCompleted(

export class AccountFetcher extends Fetcher<JobTask, AccountData[], AccountData> {
protected debug: Debugger
stateManager: DefaultStateManager

/**
* The stateRoot for the fetcher which sorts of pin it to a snapshot.
Expand Down Expand Up @@ -155,9 +159,12 @@ export class AccountFetcher extends Fetcher<JobTask, AccountData[], AccountData>
this.root = options.root
this.first = options.first
this.count = options.count ?? BIGINT_2 ** BIGINT_256 - this.first
this.stateManager = options.stateManager

this.codeTrie = new Trie({ useKeyHashing: true })
this.accountTrie = new Trie({ useKeyHashing: true })
this.accountToStorageTrie = new Map()

Check warning on line 167 in packages/client/src/sync/fetcher/accountfetcher.ts

View check run for this annotation

Codecov / codecov/patch

packages/client/src/sync/fetcher/accountfetcher.ts#L167

Added line #L167 was not covered by tests
this.debug = createDebugLogger('client:AccountFetcher')
this.storageFetcher = new StorageFetcher({
config: this.config,
Expand Down Expand Up @@ -481,6 +488,10 @@ export class AccountFetcher extends Fetcher<JobTask, AccountData[], AccountData>
return tasks
}

updateStateRoot(stateRoot: Uint8Array) {
this.root = stateRoot
}

nextTasks(): void {
if (
this.in.length === 0 &&
Expand Down
Loading

0 comments on commit 2e13846

Please sign in to comment.