@@ -19,6 +19,7 @@ const { verifyBlock, updateDifficulty } = require("../consensus/consensus");
19
19
const { parseJSON, indexTxns, numToBuffer, serializeState, deserializeState } = require ( "../utils/utils" ) ;
20
20
const jelscript = require ( "../core/runtime" ) ;
21
21
const { buildMerkleTree } = require ( "../core/merkle" ) ;
22
+ const { SyncQueue } = require ( "./queue" ) ;
22
23
23
24
const opened = [ ] ; // Addresses and sockets from connected nodes.
24
25
const connected = [ ] ; // Addresses from connected nodes.
@@ -33,15 +34,16 @@ const chainInfo = {
33
34
transactionPool : [ ] ,
34
35
latestBlock : generateGenesisBlock ( ) ,
35
36
latestSyncBlock : null ,
37
+ syncQueue : new SyncQueue ( this ) ,
38
+ syncing : false ,
36
39
checkedBlock : { } ,
37
- tempStates : { } ,
38
40
difficulty : 1
39
41
} ;
40
42
41
- const stateDB = new Level ( __dirname + "/../log/stateStore" , { valueEncoding : "buffer" } ) ;
42
- const blockDB = new Level ( __dirname + "/../log/blockStore" , { valueEncoding : "buffer" } ) ;
43
- const bhashDB = new Level ( __dirname + "/../log/bhashStore" , { valueEncoding : "buffer" } ) ;
44
- const codeDB = new Level ( __dirname + "/../log/codeStore" ) ;
43
+ const stateDB = new Level ( __dirname + "/../../ log/stateStore" , { valueEncoding : "buffer" } ) ;
44
+ const blockDB = new Level ( __dirname + "/../../ log/blockStore" , { valueEncoding : "buffer" } ) ;
45
+ const bhashDB = new Level ( __dirname + "/../../ log/bhashStore" , { valueEncoding : "buffer" } ) ;
46
+ const codeDB = new Level ( __dirname + "/../../ log/codeStore" ) ;
45
47
46
48
async function startServer ( options ) {
47
49
const PORT = options . PORT || 3000 ; // Node's PORT
@@ -189,22 +191,23 @@ async function startServer(options) {
189
191
break ;
190
192
191
193
case TYPE . REQUEST_BLOCK :
192
- if ( ! ENABLE_CHAIN_REQUEST ) { // Unsynced nodes should not be able to send blocks
193
- const { blockNumber, requestAddress } = _message . data ;
194
+ const { blockNumber, requestAddress } = _message . data ;
194
195
195
- const socket = opened . find ( node => node . address === requestAddress ) . socket ; // Get socket from address
196
+ let requestedBlock ;
197
+
198
+ try {
199
+ requestedBlock = [ ...await blockDB . get ( blockNumber . toString ( ) ) ] ; // Get block
200
+ } catch ( e ) {
201
+ // If block does not exist, break
202
+ break ;
203
+ }
196
204
197
- const currentBlockNumber = Math . max ( ... ( await blockDB . keys ( ) . all ( ) ) . map ( key => parseInt ( key ) ) ) ; // Get latest block number
205
+ const socket = opened . find ( node => node . address === requestAddress ) . socket ; // Get socket from address
198
206
199
- if ( blockNumber > 0 && blockNumber <= currentBlockNumber ) { // Check if block number is valid
200
- const block = [ ...await blockDB . get ( blockNumber . toString ( ) ) ] ; // Get block
207
+ socket . send ( produceMessage ( TYPE . SEND_BLOCK , requestedBlock ) ) ; // Send block
208
+
209
+ console . log ( `\x1b[32mLOG\x1b[0m [${ ( new Date ( ) ) . toISOString ( ) } ] Sent block at position ${ blockNumber } to ${ requestAddress } .` ) ;
201
210
202
- socket . send ( produceMessage ( TYPE . SEND_BLOCK , block ) ) ; // Send block
203
-
204
- console . log ( `\x1b[32mLOG\x1b[0m [${ ( new Date ( ) ) . toISOString ( ) } ] Sent block at position ${ blockNumber } to ${ requestAddress } .` ) ;
205
- }
206
- }
207
-
208
211
break ;
209
212
210
213
case TYPE . SEND_BLOCK :
@@ -214,45 +217,54 @@ async function startServer(options) {
214
217
block = Block . deserialize ( _message . data ) ;
215
218
} catch ( e ) {
216
219
// If block fails to be deserialized, it's faulty
217
-
218
220
return ;
219
221
}
220
222
221
- if ( ENABLE_CHAIN_REQUEST && currentSyncBlock === block . blockNumber ) {
222
- if (
223
- chainInfo . latestSyncBlock === null // If latest synced block is null then we immediately add the block into the chain without verification.
224
- || // This happens due to the fact that the genesis block can discard every possible set rule ¯\_(ツ)_/¯
225
- await verifyBlock ( block , chainInfo , stateDB , codeDB , ENABLE_LOGGING )
226
- ) {
227
- currentSyncBlock += 1 ;
228
-
229
- await blockDB . put ( block . blockNumber . toString ( ) , Buffer . from ( _message . data ) ) ; // Add block to chain.
230
- await bhashDB . put ( block . hash , numToBuffer ( block . blockNumber ) ) ; // Assign block number to the matching block hash
231
-
232
- if ( ! chainInfo . latestSyncBlock ) {
233
- chainInfo . latestSyncBlock = block ; // Update latest synced block.
234
-
235
- await changeState ( block , stateDB , codeDB , ENABLE_LOGGING ) ; // Transit state
236
- }
237
-
238
- chainInfo . latestBlock = block ; // Update latest block cache
239
-
240
- await updateDifficulty ( block , chainInfo , blockDB ) ; // Update difficulty.
241
-
242
- console . log ( `\x1b[32mLOG\x1b[0m [${ ( new Date ( ) ) . toISOString ( ) } ] Synced block at position ${ block . blockNumber } .` ) ;
243
-
244
- // Continue requesting the next block
245
- for ( const node of opened ) {
246
- node . socket . send (
247
- produceMessage (
248
- TYPE . REQUEST_BLOCK ,
249
- { blockNumber : currentSyncBlock , requestAddress : MY_ADDRESS }
250
- )
251
- ) ;
252
-
253
- await new Promise ( r => setTimeout ( r , 5000 ) ) ; // Delay for block verification
223
+ if ( ENABLE_CHAIN_REQUEST && block . blockNumber === currentSyncBlock ) {
224
+ const verificationHandler = async function ( block ) {
225
+ if (
226
+ chainInfo . latestSyncBlock === null // If latest synced block is null, we immediately add the block into the chain without verification.
227
+ || // This happens due to the fact that the genesis block can discard every possible set rule ¯\_(ツ)_/¯
228
+ await verifyBlock ( block , chainInfo , stateDB , codeDB , ENABLE_LOGGING )
229
+ ) {
230
+ await blockDB . put ( block . blockNumber . toString ( ) , Buffer . from ( _message . data ) ) ; // Add block to chain
231
+ await bhashDB . put ( block . hash , numToBuffer ( block . blockNumber ) ) ; // Assign block number to the matching block hash
232
+
233
+ if ( ! chainInfo . latestSyncBlock ) {
234
+ chainInfo . latestSyncBlock = block ; // Update latest synced block.
235
+
236
+ await changeState ( block , stateDB , codeDB , ENABLE_LOGGING ) ; // Force transit state
237
+ }
238
+
239
+ chainInfo . latestBlock = block ; // Update latest block cache
240
+
241
+ await updateDifficulty ( block , chainInfo , blockDB ) ; // Update difficulty
242
+
243
+ console . log ( `\x1b[32mLOG\x1b[0m [${ ( new Date ( ) ) . toISOString ( ) } ] Synced block at position ${ block . blockNumber } .` ) ;
244
+
245
+ chainInfo . syncing = false ;
246
+ // Wipe sync queue
247
+ chainInfo . syncQueue . wipe ( ) ;
248
+
249
+ currentSyncBlock ++ ;
250
+
251
+ // Continue requesting the next block
252
+ for ( const node of opened ) {
253
+ node . socket . send (
254
+ produceMessage (
255
+ TYPE . REQUEST_BLOCK ,
256
+ { blockNumber : currentSyncBlock , requestAddress : MY_ADDRESS }
257
+ )
258
+ ) ;
259
+ }
260
+
261
+ return true ;
254
262
}
263
+
264
+ return false ;
255
265
}
266
+
267
+ chainInfo . syncQueue . add ( block , verificationHandler ) ;
256
268
}
257
269
258
270
break ;
@@ -315,8 +327,6 @@ async function startServer(options) {
315
327
{ blockNumber : currentSyncBlock , requestAddress : MY_ADDRESS }
316
328
)
317
329
) ;
318
-
319
- await new Promise ( r => setTimeout ( r , 5000 ) ) ; // Delay for block verification
320
330
}
321
331
} , 5000 ) ;
322
332
}
@@ -514,7 +524,7 @@ async function mine(publicKey, ENABLE_LOGGING) {
514
524
515
525
// Transit state
516
526
for ( const address in storage ) {
517
- const storageDB = new Level ( __dirname + "/../log/accountStore/" + address ) ;
527
+ const storageDB = new Level ( __dirname + "/../../ log/accountStore/" + address ) ;
518
528
const keys = Object . keys ( storage [ address ] ) ;
519
529
520
530
states [ address ] . storageRoot = buildMerkleTree ( keys . map ( key => key + " " + storage [ address ] [ key ] ) ) . val ;
0 commit comments