Skip to content

Commit 285014d

Browse files
jochem-brouwerholgerd77
authored andcommitted
client: make fetcher more typesafe
1 parent eb2e4c8 commit 285014d

File tree

6 files changed

+164
-77
lines changed

6 files changed

+164
-77
lines changed

packages/client/lib/net/protocol/ethprotocol.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { BN, bufferToInt } from 'ethereumjs-util'
22
import { Block, BlockHeader, BlockHeaderBuffer } from '@ethereumjs/block'
33
import { Chain } from './../../blockchain'
44
import { Message, Protocol, ProtocolOptions } from './protocol'
5+
import { BlockBodyBuffer } from '../../../../block/dist'
56

67
interface EthProtocolOptions extends ProtocolOptions {
78
/* Blockchain */
@@ -24,7 +25,7 @@ type GetBlockHeadersOpts = {
2425
*/
2526
export interface EthProtocolMethods {
2627
getBlockHeaders: (opts: GetBlockHeadersOpts) => Promise<BlockHeader[]>
27-
getBlockBodies: (hashes: Buffer[]) => Promise<Block[]>
28+
getBlockBodies: (hashes: Buffer[]) => Promise<BlockBodyBuffer[]>
2829
}
2930

3031
const messages: Message[] = [

packages/client/lib/sync/fetcher/blockfetcher.ts

Lines changed: 16 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -4,48 +4,31 @@ import { BN } from 'ethereumjs-util'
44
import { Peer } from '../../net/peer'
55
import { EthProtocolMethods } from '../../net/protocol'
66
import { Chain } from '../../blockchain'
7+
import { Job } from '../../types'
8+
import { BlockFetcherBase, JobTask, BlockFetcherOptions } from './blockfetcherbase'
79

8-
export interface BlockFetcherOptions extends FetcherOptions {
9-
/* Blockchain */
10-
chain: Chain
11-
12-
/* Block number to start fetching from */
13-
first: BN
14-
15-
/* How many blocks to fetch */
16-
count: BN
17-
}
1810

1911
/**
2012
* Implements an eth/62 based block fetcher
2113
* @memberof module:sync/fetcher
2214
*/
23-
export class BlockFetcher extends Fetcher {
24-
protected chain: Chain
25-
protected first: BN
26-
protected count: BN
27-
15+
export class BlockFetcher extends BlockFetcherBase<Block>{
2816
/**
2917
* Create new block fetcher
3018
* @param {BlockFetcherOptions}
3119
*/
3220
constructor(options: BlockFetcherOptions) {
3321
super(options)
34-
35-
this.chain = options.chain
36-
this.maxPerRequest = options.maxPerRequest ?? 128
37-
this.first = options.first
38-
this.count = options.count
3922
}
4023

4124
/**
4225
* Generate list of tasks to fetch
4326
* @return {Object[]} tasks
4427
*/
45-
tasks(): object[] {
28+
tasks(): JobTask[] {
4629
const { first, count } = this
4730
const max = this.maxPerRequest
48-
const tasks = []
31+
const tasks: JobTask[] = []
4932
while (count.gten(max)) {
5033
tasks.push({ first: first.clone(), count: max })
5134
first.iaddn(max)
@@ -61,18 +44,18 @@ export class BlockFetcher extends Fetcher {
6144
* Requests blocks associated with this job
6245
* @param job
6346
*/
64-
async request(job: any): Promise<any> {
47+
async request(job: Job<JobTask, Block>): Promise<Block[]> {
6548
const { task, peer } = job
6649
const { first, count } = task
67-
const headers = await (peer.eth as EthProtocolMethods).getBlockHeaders({
50+
const headers = await (peer!.eth as EthProtocolMethods).getBlockHeaders({
6851
block: first,
6952
max: count,
7053
})
71-
const bodies = await peer.eth.getBlockBodies(headers.map((h) => h.hash()))
72-
const blocks = bodies.map(([txsData, unclesData]: BlockBodyBuffer, i: number) =>
54+
const bodies: BlockBodyBuffer[] = <BlockBodyBuffer[]>await peer!.eth!.getBlockBodies(headers.map((h) => h.hash()))
55+
const blocks: Block[] = bodies.map(([txsData, unclesData]: BlockBodyBuffer, i: number) =>
7356
Block.fromValuesArray([headers[i].raw(), txsData, unclesData], { common: this.config.common })
7457
)
75-
return { blocks }
58+
return blocks
7659
}
7760

7861
/**
@@ -81,18 +64,19 @@ export class BlockFetcher extends Fetcher {
8164
* @param result fetch result
8265
* @return {*} results of processing job or undefined if job not finished
8366
*/
84-
process(job: any, result: any) {
85-
if (result.blocks && result.blocks.length === job.task.count) {
86-
return result.blocks
67+
process(job: Job<JobTask, Block>, result: Block[]): Block[] | null {
68+
if (result && result.length === job.task.count) {
69+
return result
8770
}
71+
return null
8872
}
8973

9074
/**
9175
* Store fetch result. Resolves once store operation is complete.
9276
* @param {Block[]} blocks fetch result
9377
* @return {Promise}
9478
*/
95-
async store(blocks: Array<any>) {
79+
async store(blocks: Block[]) {
9680
await this.chain.putBlocks(blocks)
9781
}
9882

@@ -102,7 +86,7 @@ export class BlockFetcher extends Fetcher {
10286
* @return {Peer}
10387
*/
10488
// TODO: find out what _job is supposed to be doing here...
105-
peer(_job: any): Peer {
89+
peer(): Peer {
10690
return this.pool.idle((p: any) => p.eth)
10791
}
10892
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import { Fetcher, FetcherOptions } from './fetcher'
2+
import { BN } from 'ethereumjs-util'
3+
import { Chain } from '../../blockchain'
4+
5+
6+
export interface BlockFetcherOptions extends FetcherOptions {
7+
/* Blockchain */
8+
chain: Chain
9+
10+
/* Block number to start fetching from */
11+
first: BN
12+
13+
/* How many blocks to fetch */
14+
count: BN
15+
}
16+
17+
export type JobTask = {
18+
first: BN
19+
count: number
20+
}
21+
22+
23+
export abstract class BlockFetcherBase<JobResult> extends Fetcher<JobTask, JobResult>{
24+
protected chain: Chain
25+
protected first: BN
26+
protected count: BN
27+
28+
/**
29+
* Create new block fetcher
30+
* @param {BlockFetcherOptions}
31+
*/
32+
constructor(options: BlockFetcherOptions) {
33+
super(options)
34+
35+
this.chain = options.chain
36+
this.maxPerRequest = options.maxPerRequest ?? 128
37+
this.first = options.first
38+
this.count = options.count
39+
}
40+
41+
/**
42+
* Generate list of tasks to fetch
43+
* @return {Object[]} tasks
44+
*/
45+
tasks(): JobTask[] {
46+
const { first, count } = this
47+
const max = this.maxPerRequest
48+
const tasks: JobTask[] = []
49+
while (count.gten(max)) {
50+
tasks.push({ first: first.clone(), count: max })
51+
first.iaddn(max)
52+
count.isubn(max)
53+
}
54+
if (count.gtn(0)) {
55+
tasks.push({ first: first.clone(), count: count.toNumber() })
56+
}
57+
return tasks
58+
}
59+
}

0 commit comments

Comments
 (0)