1
1
import { BN } from 'ethereumjs-util'
2
- import VM from '@ethereumjs/vm'
3
2
import { Peer } from '../net/peer/peer'
4
3
import { short } from '../util'
5
4
import { Synchronizer , SynchronizerOptions } from './sync'
6
5
import { BlockFetcher } from './fetcher'
7
6
import { Block } from '@ethereumjs/block'
7
+ import VM from '@ethereumjs/vm'
8
+ import { DefaultStateManager } from '@ethereumjs/vm/dist/state'
9
+ import { SecureTrie as Trie } from '@ethereumjs/trie'
8
10
9
11
/**
10
12
* Implements an ethereum full sync synchronizer
11
13
* @memberof module:sync
12
14
*/
13
15
export class FullSynchronizer extends Synchronizer {
16
+ private blockFetcher : BlockFetcher | null
17
+
14
18
public vm : VM
19
+ public runningBlocks : boolean
15
20
16
- private blockFetcher : BlockFetcher | null
21
+ private stopSyncing : boolean
22
+ private vmPromise ?: Promise < void >
23
+
24
+ // Tracking vars for log msg condensation on zero tx blocks
25
+ private NUM_ZERO_TXS_PER_LOG_MSG = 50
26
+ public zeroTxsBlockLogMsgCounter : number = 0
17
27
18
28
constructor ( options : SynchronizerOptions ) {
19
29
super ( options )
20
30
this . blockFetcher = null
21
31
22
32
if ( ! this . config . vm ) {
33
+ const trie = new Trie ( this . stateDB )
34
+
35
+ const stateManager = new DefaultStateManager ( {
36
+ common : this . config . common ,
37
+ trie,
38
+ } )
39
+
23
40
this . vm = new VM ( {
24
41
common : this . config . common ,
25
42
blockchain : this . chain . blockchain ,
43
+ stateManager,
26
44
} )
27
45
} else {
28
46
this . vm = this . config . vm
29
47
//@ts -ignore blockchain has readonly property
30
48
this . vm . blockchain = this . chain . blockchain
31
49
}
50
+
51
+ this . runningBlocks = false
52
+ this . stopSyncing = false
53
+
54
+ const self = this
55
+ this . chain . on ( 'updated' , async function ( ) {
56
+ // for some reason, if we use .on('updated', this.runBlocks), it runs in the context of the Chain and not in the FullSync context..?
57
+ await self . runBlocks ( )
58
+ } )
59
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
60
+ this . chain . update ( )
61
+ }
62
+
63
+ /**
64
+ * This updates the VM once blocks were put in the VM
65
+ */
66
+ async runBlocks ( ) {
67
+ if ( ! this . running || this . runningBlocks ) {
68
+ return
69
+ }
70
+ this . runningBlocks = true
71
+ try {
72
+ let oldHead = Buffer . alloc ( 0 )
73
+ let newHead = ( await this . vm . blockchain . getHead ( ) ) . hash ( )
74
+ while ( ! newHead . equals ( oldHead ) && ! this . stopSyncing ) {
75
+ oldHead = newHead
76
+ this . vmPromise = this . vm . runBlockchain ( this . vm . blockchain , 1 )
77
+ await this . vmPromise
78
+ const headBlock = await this . vm . blockchain . getHead ( )
79
+ newHead = headBlock . hash ( )
80
+ // check if we did run a new block:
81
+ if ( ! newHead . equals ( oldHead ) ) {
82
+ const number = headBlock . header . number . toNumber ( )
83
+ const hash = short ( newHead )
84
+ const numTxs = headBlock . transactions . length
85
+ if ( numTxs === 0 ) {
86
+ this . zeroTxsBlockLogMsgCounter += 1
87
+ }
88
+ if (
89
+ ( numTxs > 0 && this . zeroTxsBlockLogMsgCounter > 0 ) ||
90
+ ( numTxs === 0 && this . zeroTxsBlockLogMsgCounter >= this . NUM_ZERO_TXS_PER_LOG_MSG )
91
+ ) {
92
+ this . config . logger . info ( `Processed ${ this . zeroTxsBlockLogMsgCounter } blocks with 0 txs` )
93
+ this . zeroTxsBlockLogMsgCounter = 0
94
+ }
95
+ if ( numTxs > 0 ) {
96
+ this . config . logger . info ( `Executed block number=${ number } hash=${ hash } txs=${ numTxs } ` )
97
+ }
98
+ }
99
+ }
100
+ } finally {
101
+ this . runningBlocks = false
102
+ }
32
103
}
33
104
34
105
/**
@@ -167,6 +238,13 @@ export class FullSynchronizer extends Synchronizer {
167
238
* @return {Promise }
168
239
*/
169
240
async stop ( ) : Promise < boolean > {
241
+ this . stopSyncing = true
242
+ if ( this . vmPromise ) {
243
+ // ensure that we wait that the VM finishes executing the block (and flushes the trie cache)
244
+ await this . vmPromise
245
+ }
246
+ await this . stateDB ?. close ( )
247
+
170
248
if ( ! this . running ) {
171
249
return false
172
250
}
@@ -177,6 +255,7 @@ export class FullSynchronizer extends Synchronizer {
177
255
delete this . blockFetcher
178
256
}
179
257
await super . stop ( )
258
+
180
259
return true
181
260
}
182
261
}
0 commit comments